d3js 强制删除不使用 exit().remove() 的旧链接

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

当我修改布局时,我无法在使用 d3js 的力导向可视化中删除旧的 links。这意味着旧的 link 不会被删除,而是保留在标签中。我确实关注 this example 并做了以下事情:

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();

其余与示例中的几乎相同。但是,我无法摆脱旧的 links,exit().remove() 将不起作用。他们将停留在可视化上。

这是我从 gilsha 执行 then 代码片段时得到的结果。 <g class="link"> 标签中的 link 行和 link 文本仍然有多个条目。它们不可见并出现在左上角,但我仍然需要摆脱它们。因为当我拖动图形时,这就成了一个问题。

在新变量中写入link.append时,它不再复制行和标签,但在调用更新时,行留在以前的位置,不再移动。

这是打勾。我需要 link link 以某种方式分组吗?

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 + ")";
      }
  });

问题中你添加的部分代码没有错误。问题将是由于代码的其他部分引起的。验证更新前后的数据集是否符合预期。

编辑:要解决 link 和文本的重复问题,请将 link 和 link 标签附加到 linkGroup 而不是 link。由于您正在为 links 使用组元素,因此 links 的动态更新可能会导致 links 的分层问题(链接可能会覆盖节点)。您可以使用代码和代码段中所示的 insert 函数解决该问题。

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 a-b
  links.pop(); // remove b-c
  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 d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })

  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>