vasturiano / 3d-force-graph Goto Github PK
View Code? Open in Web Editor NEW3D force-directed graph component using ThreeJS/WebGL
Home Page: https://vasturiano.github.io/3d-force-graph/example/large-graph/
License: MIT License
3D force-directed graph component using ThreeJS/WebGL
Home Page: https://vasturiano.github.io/3d-force-graph/example/large-graph/
License: MIT License
Hi, is it possible to change nodes and edges without forcing to reload the graph?
I try to change the size of a single node by using an external event which triggers the graph.
Everything works fine, but graphData forces the graph to reload. Only the weight of nodes has changed. No further nodes where added or edges changed etc.
Any idea how to prevent the graph from reloading.
I'd like to set styles like opacity or link width based on my data.
I tried something like Graph.nodeOpacity(d => d.opacity)
or Graph.nodeOpacity("opacity")
but it's not working.
Does anyone have a solution? thx
It would be very nice to be able to set the background color!
I'd like to try and apply aggressive depth of focus similar to http://shaderism.com/depth-of-field-with-custom-autofocus/ but am unsure of how to reference the THREE.js objects to do so. Is there a defined way to do so?
Ideally with some precision padding around the lines for usable mouse interaction.
Hello Mr. Vasturiano. Thank you very much for this wonderful framework! I am working on learning it an hope to be able to contribute back soon!!! Thank you again for all you do.
I have been able to use 3d-force-graph like this:
<script src="3d-force-graph.js"></script>
But now I am trying to set up 3d-force-graph in a React app with NPM, i am doing thus:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ForceGraph3D from '3d-force-graph';
class App extends Component {
render() {
const Graph = ForceGraph3D()
(document.getElementById("3d-graph"));
const N = 3000;
const gData = {
nodes: [...Array(N).keys()].map(i => ({ id: i })),
links: [...Array(N).keys()]
.filter(id => id)
.map(id => ({
source: id,
target: Math.round(Math.random() * (id-1))
}))
};
Graph
.cooldownTicks(300)
.cooldownTime(20000)
.autoColorBy('group')
.forceEngine('ngraph')
.graphData(gData);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<div id="3d-graph"></div>
</div>
);
}
}
export default App;
Which is according to the documentation AFAIK.
However the error I am getting is this:
TypeError: __WEBPACK_IMPORTED_MODULE_3_3d_force_graph___default(...) is not a function
render
src/App.js:9
6 | class App extends Component {
7 | render() {
8 |
> 9 | const Graph = ForceGraph3D()
10 | (document.getElementById("3d-graph"));
11 |
12 | const N = 3000;
Any pointers or suggestions would be highly appreciated!
Thank you in advance!
I notice in one of your example the use of numDimensions([int]).
In the example you delete then recreate the wole graph.
In my test, I would like to use the same data object. Updating the xyz of the nodes without deleting / recreating everything.
currently, when numDimensions is changed, the coordinates of the existing dimensions are updated as needed, but if numDimensions decrease, the coordinate persist...
It would be nice to add a step of clearing inside numDimensions method...
Here my code doing the job from outside (maybe not the best algo)
function toggleDimensions(num) {
// Save dimensions
numDim = num;
// Reset coords
if (numDim < 2) {
graph.graphData().nodes.forEach(n => {
n.y = 0;
n.vy = 0;
n.z = 0;
n.vz = 0;
});
} else if (numDim < 3) {
graph.graphData().nodes.forEach(n => {
n.z = 0;
n.vz = 0;
});
}
reloadGraph();
}
Many thanks to your work on this great library! :)
Was hoping if it would be possible to expose out a method/callback/property so that one can issue a request to stop the animation. This would be useful when navigating away from the graph to another page, as currently this just keeps on ticking and chews up CPU cycles even though the graph is no longer on the screen.
Normally this would be done by issuing the following call:
window.cancelAnimationFrame(requestID);
state.renderObjs.objects([...])
adds objects to the scene but scene does not get reset.
How to reproduce:
Call multiple times without page refresh.
Each call adds objects to the scene.
var myGraph = ForceGraph3D();
myGraph(<myDOMElement>)
.graphData(<myData>);
There is a convenient method onNodeClick(fn)
Do we have access to the node over method as well ?
By default, mouseover a node display it's name as text.
But is it possible to intersect this event and add a callback function ?
Hey @vasturiano ,
Is it possible to add a methode that will expose the objects in the state ?
The camera, the scene ?
methods: _extends({
getState: function getState(state) {
return state;
},
cameraPosition: function cameraPosition(state, position) {
// Setter
if (position) {
var x = position.x,
y = position.y,
z = position.z;
if (x !== undefined) state.camera.position.x = x;
if (y !== undefined) state.camera.position.y = y;
if (z !== undefined) state.camera.position.z = z;
state.camera.lookAt(state.forceGraph.position);
return this;
}
// Getter
return state.camera.position;
},
stopAnimation: function stopAnimation(state) {
if (state.animationFrameRequestId) {
cancelAnimationFrame(state.animationFrameRequestId);
}
return this;
}
}, linkedFGMethods),
and could you also add the tbControls to the state so that we can control the Camera LookAt ?
var tbControls = new threeTrackballcontrols(state.camera, state.renderer.domElement);
state.tbControls = tbControls;
state.renderer.setSize(state.width, state.height);
state.camera.far = 20000
Thanks
Toggleable on/off under a config property.
I need access to the simulation.on, so I'll be able to listen to the "end" event in order to change camera position after the simulation has stabilized.
If I read the source correctly, the simulation object doesn't get exported to "user land".
Thanks for your cool library!
Is it possible to let the force graph be virtually run on a node server outside a browser environment? I would like to just virtually simulate the graphing and extract the data in order to send them to connected clients (trying to synchronize their graphing displays by doing that)
Hi @vasturiano,
It's not possible to increase line width according to:
https://stackoverflow.com/questions/11638883/thickness-of-lines-using-three-linebasicmaterial
One possible replacement is https://github.com/spite/THREE.MeshLine.
Do you think it could be a good idea to support both and give the choice like for the choice between d3 and ngraph?
Cheers!
I am trying to animate edges (fading color).
In conjunction with three.js I found GSAP's TweenLite. However, for integrating TweenLite, the renderer must be accessible and on each tick update must be callable.
Is there a way to access the renderer? Is there an easier way to animate edges (e.g. fading color)?
Hi, thank you for this great library.
Would it be possible to adopt flat shading = removing shades on the spheres representing the nodes?
I guess adopting something like THREE.FlatShading
would do the trick but I have no clue where to edit that.
Hi!
Would it be possible to add custom link force a bit like this?:
{
"nodes": [
(...)
],
"links": [
{
"source": "id1",
"target": "id2",
"force": 5
},
(...)
]
}
Would it be possible to include the current build within "dist" folder in the package, so you do not have to build it yourself in case you don't want to install all the building tools on your machine?
Would it be possible to select multiple nodes using a bounding box window? I dug a little and have no idea how to add that.
Hello Vasturiano
this is my code:
var trans = [];
var ets = [];
var gData;
//Fonction pour creer un object de type automate
class Automate{
constructor(){
this.nodes = [];
this.links = [];
}
}
class Etat {
constructor(id){
this.id = id;
}
}
class Transition {
constructor(des,txt, color, next){
this.source = des;
this.txt = txt;
this.color = color;
this.target = next
}
}
//Fonction pour telecharger le fichier
function uploadFile(e) {
var file = e.target.files[0];
if (!file) {
return;
}
var read = new FileReader();
read.onload = function(e) {
var content = e.target.result;
gData = parseContent(content);
};
read.readAsText(file);
}
function validateEtat(eta){
var flag = false;
for (var i = 0; i < ets.length; i++) {
if(ets[i].id === eta){
flag = true;
}
}
if(!flag){
const eti = new Etat(eta);
ets.push(eti);
}
}
//Fonction pour parser les donnés TXT en JSON
function parseContent(content) {
//Couper chaque ligne du fichier aprés saut de ligne
var lines = content.split("\n");
//Creation de l'automate
var automateObject;
//Parcourir tout le fichier
for (var i = 0; i < lines.length-1; i++) {
//Pour creer l'onbjet automate
if(i == 0){
var currentline = lines[i].split("\n");
currentline = lines[i].replace(/[\(\)]/g, '');
currentline = currentline.replace(/,/g, '');
currentline = currentline.split(" ");
automateObject = new Automate();
const eta = new Etat(parseInt(currentline[1]));
//ets.push(parseInt(currentline[1]));
} else {
//variable pour stocker le titre et la couleur
var label;
//variable pour couper chaque ligne du fichier
var currentline = lines[i].split("\n");
//Enlever les parenthese de la chaine de characters
currentline = lines[i].replace(/[\(\)]/g, '');
//Enlever les citations de la chaine
currentline = currentline.replace(/['"]+/g, '');
//Couper la chaine en 3 morceaux
currentline = currentline.split(",",3);
//Couper le deuxieme atribut pour obtenir le nom de lien et la couleur
label = currentline[1].split(":");
//Creation d'un object de type automate
const tran = new Transition(parseInt(currentline[0]),label[0],label[1],parseInt(currentline[2]));
//Ajouter l'object dans l'array
trans.push(tran);
validateEtat(parseInt(currentline[0]));
validateEtat(parseInt(currentline[2]));
}
}
automateObject.nodes = ets;
automateObject.links = trans;
console.log(JSON.stringify(automateObject))
return JSON.stringify(automateObject);
}
function dessiner(){
const Graph = ForceGraph3D()
(document.getElementById('3d-graph'))
.graphData(gData);
}
//Asignation d'un event au bouton du fichier HTML
document.getElementById('file-input')
.addEventListener('change', uploadFile, false);
and this is my index
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test lire txt</title>
</head>
<body>
<input type="file" id="file-input" />
<button onclick="dessiner()">Print</button>
<div id="3d-graph"></div>
<script src="https://unpkg.com/[email protected]/dist/3d-force-graph.min.js"></script>
<script src="main.js"></script>
</body>
</html>
but when you click on the button, the console will display the following error
Uncaught TypeError: Cannot read property 'forEach' of undefined
at https://unpkg.com/[email protected]/dist/3d-force-graph.min.js:5:105009
at Function.tickFrame (https://unpkg.com/[email protected]/dist/3d-force-graph.min.js:5:105368)
at Function.r.(anonymous function) [as tickFrame] (https://unpkg.com/[email protected]/dist/3d-force-graph.min.js:5:91735)
at i.r.(anonymous function) [as tickFrame] (https://unpkg.com/[email protected]/dist/3d-force-graph.min.js:5:102665)
at t (https://unpkg.com/[email protected]/dist/3d-force-graph.min.js:5:119228)
and
Uncaught TypeError: Cannot read property 'length' of undefined
at Function.update (3d-force-graph.min.js:5)
at 3d-force-graph.min.js:5
at c (3d-force-graph.min.js:5)
the data that I pass is like
{"links":[{"source":0,"txt":" X","color":"BLACK","target":1},{"source":0,"txt":" X","color":"GREEN","target":2},{"source":1,"txt":" X","color":"BLACK","target":3},{"source":2,"txt":" Y","color":"GREEN","target":1},{"source":3,"txt":" X","color":"BLACK","target":1},{"source":3,"txt":" X","color":"GREEN","target":4},{"source":4,"txt":" Y","color":"GREEN","target":2},{"source":4,"txt":" X","color":"GREEN","target":5},{"source":5,"txt":" Y","color":"GREEN","target":6}],"nodes":[{"id":0},{"id":1},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6}]}
Based on the documentation it doesn't sound like it, but the thread regarding its original implementation it makes me think otherwise. Just thought I'd ask.
I have been trying to access the nodes within the scene, with the idea to pass their [x,y,z] co-ords to my django back end to run a knn model.
I have it working in a normal d3 force directed graph but im unable to select all nodes in this and apply them to a var.
Thanks in advance!
Great library! I have a few questions/requests. Is it possible to have a shape other than a sphere? Can an image be applied as a texture to the node? And can labels always be shown instead of just with mouseover?
Hi @vasturiano,
Is it possible to change the initial data without reloading everything with Graph.graphData({ nodes, links });?
Thanks,
Thank you for the fantastic library.
I'm looking to add moving particle systems within the links like the photon animation in this video: https://www.youtube.com/watch?v=JsEm-CDj4qM. Would it be possible?
Hello I just try to install the package with npm (v1.10.0) and I get an error
$ npm install 3d-force-graph
npm ERR! tar.unpack untar error C:\Users\Maxime Hebrard\AppData\Roaming\npm-cache\3d-force-graph\1.10.0\package.tgz
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\react-scripts\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! Windows_NT 10.0.15063
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "3d-force-graph"
npm ERR! node v7.4.0
npm ERR! npm v4.0.5
npm ERR! path D:\iclikval-links3d\node_modules\.staging\3d-force-graph-ea2ba592\:q
npm ERR! code ENOENT
npm ERR! errno -4058
npm ERR! syscall open
npm ERR! enoent ENOENT: no such file or directory, open 'D:\iclikval-links3d\node_modules\.staging\3d-force-graph-ea2ba592\:q'
npm ERR! enoent ENOENT: no such file or directory, open 'D:\iclikval-links3d\node_modules\.staging\3d-force-graph-ea2ba592\:q'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! Please include the following file with any support request:
npm ERR! D:\iclikval-links3d\npm-debug.log
Any idea how to fix it ?
Hi there,
Thank you very much for this great library. Unfortunately, I ran into a problem.
The ngraph and the default d3 force layout algorithms differ; the former resets the layout whereas the latter does not when a node or edge is added/removed.
As a consequence, I cannot use the ngraph algorithm, even though it gives better results.
For instance, see an adjusted version of the "dynamic example": https://jsfiddle.net/97ov1cz6/5/
Is it possible to change camera position on node focus in transition, not jumping instantly?
Hello, could you please create an example where you make use of this function?
I have trouble to understand it.
It could be nice to be able to take a screenshot of the view.
I tested with
$('canvas')[0].toDataURL("image/png");
but the canvas is empty.
If I understand well, we need to access the renderer and convert it to png
renderer.domElement.toDataURL()
see an example there:
https://stackoverflow.com/questions/40444995/how-to-convert-render-from-three-js-to-png-file
It would me nice to have this kind of feature in 3d-force-graph, something like
myGraph.screenshot()
With maybe an option for new background color, or transparent background (is that too much? ^.^")
Once cameraPosition
was set manually, pan (right mouse down, move) does not work anymore. Is that intended? Other controls (zoom, rotate) are still working properly.
Hi, look, I do not know if I've already talked to you about the subject but I'm trying to do this
At the beginning I paint a graph as indicated by your documentation with the variable
Graph = ForceGraph3D ()
with the functions that I need, but in a certain point of my application I want to paint another graphic but different from the one that is already painted. I use the same variable that is "Graph" with the exception that now I pass new data to draw them
but what it does is just draw me the new graphic on which it was already drawn. I sent you an image of the problem
The all white graphic is the new one that I painted
Image example link https://ibb.co/m0E4xS
I tried to declare the variable "Graph = null" to delete everything but it does not work
the only solution I've seen is to reload the entire page, would like to know if there is a possibility to paint a new graphic without reloading the page?
backgroundColor([str]) fetches the default color and sets new color but change is displayed
I used THREE --> new THREE.PerspectiveCamera()
in nodeThreeObject()
-->Error
How to set up Camera?
HELP ME (っ °Д °;)っ
Is there an easy way to set the font colour for the labels in the auto colored example?
Hi Vasturiano,
First of all, really great piece of work on all force graphs here. Thanks a ton. I am trying both force-graph and also 3D one.
The Text on Node example does not show text any more, can you please check ?
https://vasturiano.github.io/3d-force-graph/example/text-nodes/
Actually, my scenario is show text for group nodes, basically these will be source nodes and show sphere or circle for the target nodes and show text label on target node hover. Also wish to hide/show all other nodes except clicked node and its source/targets. I tried to load 10K+ nodes and it loaded pretty faster than expected.
Thanks
Hi thank you for the great library!
Is it possible to rotate the visual/graph automatically?
Hello Mr. Vasturiano! I am using 3d-force-graph in a React app like in #10 , and I need to click to focus.
This is my code:
<Graph
graphData={this.state.data}
cameraPosition={[[this.state.poi],[this.state.target]]}
linkWidth={l=>{
if(l.emphasis){
return 0.6;
}
return null;
}}
onNodeClick={node => {
const count = 10;
// Graph.cameraPosition({ x: node.x +100- count, y: node.y +100- count, z: node.z +100- count }, node);
this.setState({poi: { x: node.x +100- count, y: node.y +100- count, z: node.z +100- count }, target: [node]});
}}
/>
And the following error is displayed:
TypeError: Cannot set property 'target' of undefined
Function.cameraPosition
node_modules/3d-force-graph/dist/3d-force-graph.module.js:197
194 | if (y !== undefined) state.camera.position.y = y;
195 | if (z !== undefined) state.camera.position.z = z;
196 |
> 197 | state.tbControls.target = lookAt ? new three.Vector3(lookAt.x, lookAt.y, lookAt.z) : state.forceGraph.position;
198 |
199 | return this;
200 | }
Do you have any suggestions?
Thank you! @vasturiano
Building project during npm install fails because the script is using linux commands that are not available on windows.
In package.json you have the line "build": "rm -rf dist && mkdir dist rollup -c"
- but the command rm
does not exist on windows. I delete evereything except rollup -c
from that line and created the dist folder manually. That seemed to work, but maybe there are more issues on windows that I didn't discover yet.
Hello @vasturiano ,
First of all thanks for the fantastic library!
I have a requirement where I'd like a "floor" to appear beneath my 3D force graph - essentially a plane geometry with image texture. Is there a function I can call on the ForceGraph3D object to achieve this?
Best Regards,
@Piyush3dB
It could be nice to have access to the camera position.
Let say, when user click on one node, the camera pan at a certain distance of that node.
using onNodeClick(fn) we can trigger an event on click,
but there is no way (as far as I know) to modify the camera position programmatically.
First, thanks for this great contribution.
If you have a moment, could you expose the state.d3ForceLayout object in the Graph(), so users can adjust the forces without having to edit and recompile this module?
now,only when my mouse moves to the top will it be displayed
thank you
First, it is a fantastic application.
My question: How is it possible to access the active scene?
Hi,
It could be cool to have some kind of support when we have multiple links for the same sources and targets.
Right now, if we have several links for the same source and same target, the two lines representing the links are at the same place which makes it difficult to visually see, hover or select them.
Cheers
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.