Emil Stolarsky
Emil Stolarsky

Reputation: 108

D3.js Force Layout: Dynamically added node doesn't move with rest of graph

I'm working on building a molecule creator in D3 using the original example created by Mike Bostock: http://bl.ocks.org/mbostock/3037015

I'm using a force layout just like in the example. My problem is when I add a new Node/atom dynamically, it doesn't move with the rest of the graph. I've read other questions and implemented everything that is suggested and have made sure that I'm following the proper update/join procedure that D3 requires and yet still the added carbon refuses to move with the rest of the graph.

Here is my update/create function:

function buildMolecule () {
    // Update link data
    link = link.data(links);

      // Create new links
    link.enter().append("g")
          .attr("class", "link")
          .each(function(d) {
            d3.select(this)
              .insert("line", ".node")
              .style("stroke-width", function(d) { return (d.bond * 2 - 1) * 2 + "px"; });

            d3.select(this)
              .filter(function(d) { return d.bond > 1; }).append("line")
              .attr("class", "separator");

            d3.select(this)
              .on("click", bondClicked);
    });

    // Delete removed links
    link.exit().remove();    

    // Update node data

    node = node.data(nodes);

    // Create new nodes
    node.enter().append("g")
          .attr("class", "node")
          .on("click", atomClicked)
          .each(function(d) {
            console.log('d:', d);
            // Add node circle
              d3.select(this)
                .append("circle")
                .attr("r", function(d) { return radius(d.size); })
                .style("fill", function(d) { return color(d.atom); });

            // Add atom symbol
              d3.select(this)
                .append("text")
                .attr("dy", ".35em")
                .attr("text-anchor", "middle")
                .text(function(d) { return d.atom; });

                d3.select(this).call(force.drag);
            });

      // Delete removed nodes
    node.exit().remove();

    force.start();
}

JsFiddle: http://jsfiddle.net/2dPMF/1/

Any help would be greatly appreciated!

Upvotes: 2

Views: 1976

Answers (1)

Lars Kotthoff
Lars Kotthoff

Reputation: 109282

You're modifying the data structures of the nodes and links beyond adding and deleting nodes, which messes up the force layout. I'm talking about these lines in particular.

function bigBang () {
    links = links.concat(linksList);
    nodes = nodes.concat(nodesList);
    buildMolecule();
  }

The first two lines in that function are what I'm talking about. Working jsfiddle here.

Upvotes: 3

Related Questions