Moving Fixed Nodes in D3

I have nodes in the D3 syntax layout that are set to .fixed = true. If I set the values ​​to .x or .y, the nodes themselves do not move to their new position.

Here is my function:

function fixNode(idArray, locationX, locationY) { for ( x = 0; x < idArray.length; x++ ) { for ( y = 0; y < nodes.length; y++ ) { if (nodes[y].id == idArray[x]) { nodes[y].fixed = true; nodes[y].x = 50; nodes[y].y = 50; break; } } } } 

UPDATE 1:

Here is a working function based on Jason's advice:

 function fixNode(idArray, locationX, locationY) { for ( x = 0; x < idArray.length; x++ ) { for ( y = 0; y < nodes.length; y++ ) { if (nodes[y].id == idArray[x]) { nodes[y].fixed = true; nodes[y].x = 50; nodes[y].y = 50; nodes[y].px = 50; nodes[y].py = 50; break; } } } tick(); } 
+7
javascript force-layout
source share
1 answer

The force-oriented layout is separate from the actual rendering. Usually you have a tick handler that updates the attributes of your SVG elements for each tick of the layout algorithm (the nice thing about decoupling is to do this instead of <canvas> or something else).

To answer your question, you just need to call this handler directly to update the attributes of your SVG elements. For example, your code might look like this:

 var node = …; // append circle elements var force = d3.layout.force() .nodes(…) .links(…) .on("tick", tick) .start(); function tick() { // Update positions of circle elements. node.attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); } 

Thus, you can simply call tick() at any point and update the position of the elements.

You may be tempted to call force.tick() , but this is intended to be used as a synchronous alternative to force.start() : you can call it again, and each call performs a step in the layout algorithm. However, there is an internal variable alpha , used to control the simulated annealing used internally, and after the layout has β€œcooled”, this variable will be 0 and further calls to force.tick() will have no effect. (Admittedly, it would be nice if force.tick() always triggered a tick event regardless of cooling, but this is not the current behavior).

As you correctly noted in the comments, if you manually set dx and dy , you should also set d.px and d.py with the same values ​​if you want the node to stay in a certain position.

+12
source share

All Articles