Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update elements of D3 force layout when the underlying data changes

I'm using one of the force layout examples (http://bl.ocks.org/1153292) to show a network on my web site.

I allow the user to choose which type of links to see at any given time. I notice that when I choose to see link type A, then add link type B and then remove link type A the remain links of type B are presented with A colors.

This is the code that runs to add the links to the svg diagram. I am changing the array this.links by adding and removing links from it. As you can see I set the class attribute but it is not updating - it remains of type of link A.

var path = svg.append("svg:g")
    .selectAll("path")
    .data(this.links)
   .enter()
    .append("svg:path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

I currently work around this problem by updating the class attribute inside the tick function but this off course cause much un-needed work.

I read that the enter operation return a merged selection of the exist elements and also the new ones so the attr operation should update the exist one and set the new one.

What am I missing?

like image 587
Ido Ran Avatar asked Oct 20 '12 20:10

Ido Ran


2 Answers

I've found the answer in this post

var circle = svg.selectAll("circle")
    .data(data);

circle.enter().append("circle")
    .attr("r", 2.5);

circle
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; });

circle.exit().remove();

The answer is that I need to call attr operator on the result of selectAll.data and not on the result of the append operator.

like image 80
Ido Ran Avatar answered Nov 03 '22 01:11

Ido Ran


There is an example at http://bl.ocks.org/1095795 that shows adding and removing nodes from a force directed layout. The links and nodes have to be handled separately and then the force layout has to be restarted.

function restart() {
  var link = vis.selectAll("line.link")
      .data(links, function(d) { return d.source.id + "-" + d.target.id; });

  link.enter().insert("svg:line", "g.node")
      .attr("class", "link");

  link.exit().remove();

  var node = vis.selectAll("g.node")
      .data(nodes, function(d) { return d.id;});

  var nodeEnter = node.enter().append("svg:g")
      .attr("class", "node")
      .call(force.drag);

  nodeEnter.append("svg:image")
      .attr("class", "circle")
      .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
      .attr("x", "-8px")
      .attr("y", "-8px")
      .attr("width", "16px")
      .attr("height", "16px");

  nodeEnter.append("svg:text")
      .attr("class", "nodetext")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.id });

  node.exit().remove();

  force.start();
}
like image 42
Bill Avatar answered Nov 03 '22 00:11

Bill