简体   繁体   中英

d3js force-directed removal of old links not working with exit().remove()

Im unable to remove old links in my force-directed visualization with d3js, when I modify the layout. That means the old link will not be deleted and instead stay in the tag. I did follow this example and did the following:

link = link.data(links, function(d) { 
  return d.source.id + '-' + d.target.id; 
});
link.enter().append("g").attr("class", "link");
var linkline = link.append("line").attr("class", "linkline");
var linktext = link.append("text").attr("class", "linktext")
  .text(function(d) {
    return d[setup.label_edge];
});
link.exit().remove();

The rest is pretty much the same as in the example. However, I cant get rid of the old links, exit().remove() won't work. They will stay on the visualization. 如您所见。

This is what I get when I execute then code snippet from gilsha. There are still multiple entries for linkline and linktext in the <g class="link"> -tag. They are not visible and appear in the upper left corner, but I still need to get rid of them. Because when I drag the graph this becomes a problem. 在此处输入图片说明

When writing the link.append in a new variable, it does not duplicate the lines and labels anymore, but when calling update the lines stay in the previous position and don't move anymore.

在此处输入图片说明

This is the tick. Do I need to link linkGroup somehow?

force.on("tick", function(e){
      linkline
      .attr("x1", function(d) { 
         return d.source.x; 
      })
      .attr("y1", function(d) { 
         return d.source.y; 
      })
      .attr("x2", function(d) { 
         return d.target.x; 
      })
      .attr("y2", function(d) { 
         return d.target.y;
      });
      linktext
        .attr("x", function(d) {
          return ((d.source.x + d.target.x)/2);
        })
        .attr("y", function(d) {
          return ((d.source.y + d.target.y)/2);
        });


  node.attr("transform", function(d) {
    if(setup.source == 0) {
      if(d.id==0){
        damper = 0.1;
        d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
        d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
      }
      var x = Math.max(radius, Math.min($('svg').attr('width')  - radius, d.x));
      var y = Math.max(radius, Math.min($('svg').attr('height') - radius, d.y));
      return "translate(" + x + "," + y + ")";
    } else {
        if(d.id==0){
          damper = 0.1;
          d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
          d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
        }
        var x = Math.max(radius, Math.min($('svg').attr('width')  - imagesize2(d.metadata[setup.external[1]])[0], d.x));
        var y = Math.max(radius, Math.min($('svg').attr('height') - imagesize2(d.metadata[setup.external[1]])[1], d.y));
        return "translate(" + x + "," + y + ")";
      }
  });

There is no error in the part of code you added in the question. The problem will be due to some other part of the code. Verify the dataset is as expected before and after update.

EDIT: To resolve the duplication of links and texts, append links and link labels to linkGroup rather than link . Since you are using group elements for links, dynamic update of links may cause layering issues of links(Links may lay over nodes). You can resolve that issue by using insert function as shown in code and snippet.

link = link.data(links, function(d) {
    return d.source.id + '-' + d.target.id;
});

/* var linkGroup = link.enter().insert("g",".node").attr("class", "link");//Use insert to resolve dom element layering issue. */

var linkGroup = link.enter().append("g").attr("class", "link");  

var linkline = linkGroup.append("line")
   .attr("class", "linkline");

var linktext = linkGroup.append("text")
    .attr("class", "linktext")
    .text(function(d, i) {
      return i;
    });  

link.exit().remove();

 var width = 960, height = 500; var color = d3.scale.category10(); var nodes = [], links = []; var force = d3.layout.force() .nodes(nodes) .links(links) .charge(-400) .linkDistance(120) .size([width, height]) .on("tick", tick); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var node = svg.selectAll(".node"), link = svg.selectAll(".link"); // 1. Add three nodes and three links. setTimeout(function() { var a = { id: "a" }, b = { id: "b" }, c = { id: "c" }; nodes.push(a, b, c); links.push({ source: a, target: b }, { source: a, target: c }, { source: b, target: c }); start(); }, 0); // 2. Remove node B and associated links. setTimeout(function() { nodes.splice(1, 1); // remove b links.shift(); // remove ab links.pop(); // remove bc start(); }, 3000); // Add node B back. setTimeout(function() { var a = nodes[0], b = { id: "b" }, c = nodes[1]; nodes.push(b); links.push({ source: a, target: b }, { source: b, target: c }); start(); }, 6000); function start() { link = link.data(links, function(d) { return d.source.id + '-' + d.target.id; }); var linkGroup = link.enter().insert("g",".node").attr("class", "link"); //Use insert to resolve dom element layering issue. //var linkGroup = link.enter().append("g").attr("class", "link"); var linkline = linkGroup.append("line") .attr("class", "linkline"); var linktext = linkGroup.append("text") .attr("class", "linktext") .text(function(d, i) { return i; }); link.exit().remove(); node = node.data(force.nodes(), function(d) { return d.id; }); node.enter().append("circle").attr("class", function(d) { return "node " + d.id; }).attr("r", 8); node.exit().remove(); force.start(); } function tick() { node.attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }) link.selectAll("line").attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); } 
 .link { stroke: #000; stroke-width: 1.5px; } .node { fill: #000; stroke: #fff; stroke-width: 1.5px; } .node.a { fill: #1f77b4; } .node.b { fill: #ff7f0e; } .node.c { fill: #2ca02c; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM