Is it possible to preserve Node Positions in a Force Dircted Graph between updates?

688 views
Skip to first unread message

Chris

unread,
May 31, 2012, 10:23:06 AM5/31/12
to d3...@googlegroups.com
I have a force layaout graph.

I periodically update it with additional nodes and links 

On updating, some of the nodes are existing nodes, and some are brand new nodes.

Is it possible to preserve the position of the existing nodes so that the graph is not completely re done from scratch each time?

rafe purnell

unread,
May 31, 2012, 11:03:12 AM5/31/12
to d3...@googlegroups.com

I hit this same thing a few weeks back. Not resolved it... :-( but not had time really.

I know that when nodes are reloaded the force still generates random locations upon entry. Causing the huge wobble at load time.

I tried using the previous location px py (I think) when loading but that did not seem to work.

Hope someone has done this before. Would be really nice.

Jamie Popkin

unread,
May 31, 2012, 11:46:59 AM5/31/12
to d3...@googlegroups.com
This is how I did it:

1. Stop the force. eg. myObj.force.stop()
2. Save node positions to an object:
d3.selectAll(".node").map(function (d) {
      if (d) { myObj.prevLoc[d.name] = [d.x,d.y];}
});
3. Load your data or whatever you're going to do.
4. Stuff the old locations back into the nodes:

d3.selectAll(".node").map(function (d) {

if (myObj.prevLoc[d.name]) {
         oldX = myObj.prevLoc[d.name][0];
         oldY = myObj.prevLoc[d.name][1];
} else {
         // If no previous coordinate... Start from off screen for a fun zoom-in effect .
         oldX = -100;
         oldY = -100;
}

return {
         id: d.name+"-node",
         name: d.name,
         x: oldX,
         y: oldY,
         px: oldX,
         py: oldY,
         index: d.index};
}

5. Restart the force. eg. myObj.force.start()


When updating the data... It's kinda important to bind by a unique value. Hence preserving the relationship of attributes to their corrects nodes. You can use the index attribute for this. Otherwise it goes random.

Hope that helps. :)

--
Jamie Popkin
Little Earth

Chris Michael

unread,
May 31, 2012, 11:50:37 AM5/31/12
to d3...@googlegroups.com
" Hope that helps. :) "

Just a bit!! This is exactly what I am after. ;-)

This is a very elegant solution. Thanks very much, it looks like exactly what I need.

rafe purnell

unread,
May 31, 2012, 7:27:21 PM5/31/12
to d3...@googlegroups.com

Looks ideal... Will give it a try... :-)

Jamie Popkin

unread,
May 31, 2012, 8:20:37 PM5/31/12
to d3...@googlegroups.com
I think I forgot one step in point 2.... You have to return the data object... Or the bound data will essentially be stripped out.

It should look like this:

2. Save node positions to an object:
d3.selectAll(".node").map(function (d) {
if (d) { myObj.prevLoc[d.name] = [d.x,d.y];}
return d;

ddom...@gmail.com

unread,
Jan 6, 2017, 5:16:39 AM1/6/17
to d3-js
What does 'myObj' refers to? the svg object?
Reply all
Reply to author
Forward
0 new messages