I am trying to create a force diagram that gets re-centered on click.
I am following this as a base:
I tried to adjust the click function to set d.fixed=true
and also assign fixed points for d.x
and d.y
.
However, I need to turn d.fixed=false
for all the other nodes. Also, the node does not transition to the center on click.
My question is how do I set all other fixed properties to false and then redraw the force diagram with the new center?
I have prepared an example here:
The click function is fairly straightforward:
function click(d) {
d.fixed=true;
d.x=10;
d.y=10;
update();
}
I tried adding this to the function:
root.forEach(function (d) { d.fixed = false; });
You can access the nodes using force.nodes()
and iterate to set the fixed
attribute to false
.
force.nodes().forEach(function(d) { d.fixed = false; });
and then update the graph. I forked your example here and added a double click listener that restart the force layout. Regards,
A few things, in the order I approached the problem. Here's the final fiddle if you want to follow along.
First, your update()
method does a lot more than just update the position of the nodes; it recalculates the whole tree. It's overkill for what you're trying to do, and while in the end it turned out to not be the source of the problem, I'd still recommend just using force.resume()
to get the timer ticking and the nodes moving again.
Second, you were on the right track with adding a forEach
statement to turn off the former fixed nodes. But forEach
works on arrays, and root
is an object. So either reuse the flatten
method (slow) or do as @Pablo suggested and use force.nodes() to get the nodes as an array (better).
Third, and this took a bit to figure out: Once you set a node to be "fixed", the force layout ignores any new d.x and d.y values, resetting them back to d.px and d.py (the previous values). (I assume this is so that if the node is dragged, it will automatically jump back to its fixed position). So to move it to be fixed where you want it to be, you have to set the "previous" values, not the new values. The only problem is that this causes an immediate jump in position, instead of a smooth movement. You might want to add in a transition for that one node (to make it look like it's being dragged to the centre) before calling force.resume()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With