简体   繁体   中英

How to make it so D3 Force Directed Graph generates nodes in same position each time

When I call d3.start() on a d3.js force directed I generate a graph with nodes and edges in particular locations. However, when I call start again with the same data, the positioning of the nodes is different than previously. Is there a way to make it so that nodes are positioned in the same positions each time?

Do I absolutely set the first nodes position, and then somehow position relatively to that first nodes position each time?Thanks.

My code for building the d3-force graph is boilerplate.

And following my collection of data from my internal json and creating the node and link objects I call

setTimeout(function(){
    var n = node.size();
    node.forEach(function(d, i) {
      d.x = d.y = width / n * i;
    });
    console.log(node);
    setTimeout(function(){
      force.start();
      for (var i = 0; i < n; ++i) force.tick();
      force.stop();
    },300);
},100);

where node is the array of circle objects I use for nodes...Also it does not seem like the nodes are initializing along the diagonal for when I first call start. Any thoughts? Thanks!

According to the d3 documentation, aligning your nodes along a diagonal line, will make the force directed algorithm balance the nodes positions with the least number of iterations in most cases.

I use it this way and I get consistent positions every time I use the same data set.

The number of iterations depends on the graph size and complexity. The choice of initial positions can also have a dramatic impact on how quickly the graph converges on a good solution. For example, here the nodes are arranged along the diagonal:

var n = nodes.length;
nodes.forEach(function(d, i) {
  d.x = d.y = width / n * i;
});

From: https://github.com/mbostock/d3/wiki/Force-Layout

This means that setting your nodes' positions is redundant. Let the force directed sort all the positions for you, by calling .start() after you've done something similar to the code above.

Yeah, it's a simple way to layout according to the first position, resume the x and y before next force layout

data.forEach((e)=>{
  e.x = e.firstX
  e.y = e.firstY
})

layout(data)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM