J'essaie de reproduire this example ("Static Force Layout" by Mike Bostock) dans D3 v4.Disposition de la force statique dans D3 v4
J'ai combiné le code de Mike avec ce que j'ai appris en créant un graphique de force dynamique (qui peut être trouvé here). Je pensais (peut-être à tort) qu'un graphique de force statique serait plus facile, mais je ne comprends pas complètement la logique du tutoriel de Mike et je ne peux pas le «traduire en langage v4».
Dans l'exemple de Mike à chaque fois que la page est mise à jour les noeuds prennent une position différente. Ma compréhension est que l'opération de chaque tick déplace chaque nœud au hasard. Par conséquent, la position est déterminée (de manière aléatoire) par cette partie du code:
// Use a timeout to allow the rest of the page to load first.
setTimeout(function() {
// Run the layout a fixed number of times.
// The ideal number of times scales with graph complexity.
// Of course, don't run too long—you'll hang the page!
force.start();
for (var i = n * n; i > 0; --i) force.tick();
force.stop();
svg.selectAll("line")
.data(links)
.enter().append("line")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 4.5);
loading.remove();
}, 10);
Où n est défini arbitrairement.
Voilà comment je traduis cette partie:
setTimeout(function() {
var simulation = d3.forceSimulation()
.force('link', d3.forceLink().id(function (d) { return d.ID; }))
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width/2, height/2));
var n = 1000;
//I thought that since I have many nodes and edges in my graph I should use a highgher n. However, wheter n=10 or 1000 nothing changes in the final result
for (var i = n * n; i > 0; --i) simulation.tick();
simulation
.nodes(data.nodes)
.on('tick', ticked);
simulation.force('link')
.links(data.edges)
.distance(distance);
function ticked() {
d3.selectAll('circle')
.attr('cx', function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr('cy', function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
d3.selectAll('line')
.attr('x1', function(d) { return d.source.x; })
.attr('y1', function(d) { return d.source.y; })
.attr('x2', function(d) { return d.target.x; })
.attr('y2', function(d) { return d.target.y; });
}
//Strange fact: I need to have both this tick function and the position attributes for each node and edge for the visualization to show something.
simulation.stop();
var link = graph.append("g")
.attr('class', 'links')
.selectAll("line")
.data(data.edges)
.enter()
.append("line")
.attr('x1', function(d) { return d.source.x; })
.attr('y1', function(d) { return d.source.y; })
.attr('x2', function(d) { return d.target.x; })
.attr('y2', function(d) { return d.target.y; });
var node = graph.append("g")
.attr('class', 'nodes')
.selectAll("circle")
.data(data.nodes)
.enter()
.append("circle")
.attr("r", radius)
.attr('fill', 'red')
.attr('cx', function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr('cy', function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
loading.remove();
}, 10);
Toute idée de ce que je fais mal?