1

I want the old nodes in the force layout to keep their position/momentum/fixedness, when i update the graph with new nodes.

The update adds and removes nodes and links, but the server only sends {name: _}, and doesn't know about the rest, i.e. {x: _, y: _, px: _, py: _, fixed: _}.

Now, I'm manually merging each:

var names = {};
// stores old nodes, indexed by _.name

function merge(nodes) {
    for (var i=0; i < nodes.length; i++) {

        var next = nodes[i];
        var prev = names[nodes[i].name]; // defaults to null
        var node = $.extend(true, {}, next, prev); // merge old into new
        nodes[i] = node;

        names[node.name] = node;
    }
    return nodes;
}

d3.json(function(error, graph){
    merge(graph.nodes)
    force.nodes(graph.nodes);
    ...
}

Is there a better way to do this? Maybe some d3 function that takes the two data (i.e. the old and the new) and outputs one (to be used as the new), that's called by the data join? selection.data() only takes a key.

This example replaces the nodes, rather than merging them.

Related: Problems adding and removing nodes in a force-layout using d3.js

Community
  • 1
  • 1
sam boosalis
  • 1,997
  • 4
  • 20
  • 32

1 Answers1

1

D3 doesn't provide any functionality to do what you're looking for, but you've already implemented merge, which does the same thing. Basically, you need to modify the data structures that you gave to force.links() and force.nodes(). There is no need to tell the force layout to use them explicitly after making the changes.

Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204