【问题标题】:d3js force-directed removal of old links not working with exit().remove()d3js 强制删除旧链接不适用于 exit().remove()
【发布时间】:2016-05-16 22:48:12
【问题描述】:

当我修改布局时,我无法使用 d3js 删除强制导向可视化中的旧链接。这意味着旧链接不会被删除,而是保留在标签中。我确实关注了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();

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

这是我从 gilsha 执行 then 代码 sn-p 时得到的。 <g class="link">-tag 中仍有多个 linkline 和 linktext 条目。它们不可见并出现在左上角,但我仍然需要摆脱它们。因为当我拖动图表时,这会成为一个问题。

将link.append写入新变量时,它不再重复行和标签,但在调用update时,行保持在以前的位置并且不再移动。

这是勾号。我需要以某种方式链接 linkGroup 吗?

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

【问题讨论】:

    标签: javascript d3.js force-layout


    【解决方案1】:

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

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

    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>

    【讨论】:

    • 谢谢。当我执行此代码时,我将获得三个 标记,其中包含链接线和链接文本。到现在为止还挺好。但是其中一个又重复了(旧)条目。
    • 这几乎可以做到。链接不再重复,但线条没有移动并保持在先前的位置。添加了屏幕截图。
    • 你的tick函数是什么样子的?您可以将其添加到您的问题中吗?
    • 好的。显然我错过了添加 selectAll("line")。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    相关资源
    最近更新 更多