score:0

Accepted answer

D3-force replaces the source and target properties in your links from some identifier for a given node to the node's object reference itself. Consequently, all links consist of source and target object references, the node object references themselves.

Using JSON.parse and JSON.stringify to store/re-create the data doesn't result in an object where links and nodes share object references: node and link contain object references to different objects (even if they look identical):

Below sees if a link source is the same as a node, which it is after the force is initialized, but isn't after parsed and stringified.

var graph = {
  nodes: [
    {id: 1},
    {id: 2}
  ],
  links : [
    {source: 1, target: 2}
  ]
}

var force = d3.forceSimulation()
  .nodes(graph.nodes)
  .force("link", d3.forceLink().id(d=>d.id).links(graph.links));
  
// force only:
console.log(graph.nodes[0] == graph.links[0].source);

// parsed:
graph = JSON.parse(JSON.stringify(graph))
console.log(graph.nodes[0] == graph.links[0].source);

// For comparison:
console.log("graph.nodes[0]:")
console.log(graph.nodes[0])
console.log("graph.links[0].source:")
console.log(graph.links[0].source)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

If you are only creating/removing nodes, you could reload the links from the starting links array each time, storing only the nodes. Then, by re-initializing node and link, you should get a new force layout with the node positions (and consequently links) in their last positions.

If you are adding/removing links then you could use an alternative method of parsing the object, such as Flatted, which appears to work on a force layout:

var graph = {
  nodes: [
    {id: 1},
    {id: 2}
  ],
  links : [
    {source: 1, target: 2}
  ]
}

var force = d3.forceSimulation()
  .nodes(graph.nodes)
  .force("link", d3.forceLink().id(d=>d.id).links(graph.links));
  
// force only:
console.log(graph.nodes[0] == graph.links[0].source);

// parsed:
graph = Flatted.parse(Flatted.stringify(graph))
console.log(graph.nodes[0] == graph.links[0].source);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatted@3.1.1/min.js"></script>


Related Query