D3.js添加标签链接

时间:2016-03-16 14:42:27

标签: d3.js

我正在使用强制布局,我想在现有图表上添加带有链接的新节点。

添加节点不是问题,我的链接有问题。

我在这样的链接上添加了标签:image link

以下是我用来绘制链接的代码:

  var link = svg.selectAll(".link");
  var links = []; // link array with source and target

    [...]    

var force = d3.layout.force()
        .nodes(nodes)
        .links(links)

[...]

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

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

        linkLine = appendL.append("line")
                .attr("class", "linkLine")
                .style("stroke-width", 1);

        linkLabel = appendL.append("text")
                .attr("class", "linkLabel")
                .attr("dy", 5)
                .attr("filter", "url(#solid)")
                .text(function (d) {
                    return d.type;
                });

        link.exit().remove();

(过滤器用于在标签上添加白色背景)。

但是当我更改链接列表时,结果如下:image link

新链接可以移动,但旧链接是固定的,不会附加到节点。

我认为D3在检测图表上是否已存在链接时遇到问题。

如果您有任何想法......谢谢!

PS:对不起我的英文。

1 个答案:

答案 0 :(得分:1)

基本上你没有选择所有的行来更新它们。

当你更新它们时,你需要选择已经存在的东西来“覆盖”它。所以将其移到更新功能中:

  node = svg.selectAll(".node").data(nodes)
  link = svg.selectAll(".linkLine").data(links);

注意我在.linkLine上使用了selectAll。这就是你给链接一个linkLine类,所以我们需要选择它们。你附加这条线的方式也是错误的。这是正确的方法:

linkLine = link.enter().append("line")
    .attr("class", "linkLine")
    .style("stroke-width", 1);

  linkLabel = link.append("text")
    .attr("class", "linkLabel")
    .attr("dy", 5)
    .attr("filter", "url(#solid)")
    .text(function(d) {
      return d.type;
    });

  link.exit().remove();

这是您更新的小提琴:https://jsfiddle.net/reko91/wdouvab8/1/

还需要做标签。由于你不能将文字附加到svg中的一行,我能想到的最好的方法就是用标签做类似的事情。

使用链接数据创建容器:

linkLabelContainer = svg.selectAll(".linkLabel").data(links);

创建实际的文本元素:

 linkLabel = linkLabelContainer.enter().append("text")
    .attr("class", "linkLabel")
    .attr("dy", 5)
    .attr("filter", "url(#solid)")
    .text(function(d) {

      return d.type;
    });

不要忘记删除:

linkLabelContainer.exit().remove();

现在位置:

linkLabelContainer.attr("transform", function(d) { //calcul de l'angle du label
    var angle = Math.atan((d.source.y - d.target.y) / (d.source.x - d.target.x)) * 180 / Math.PI;
    return 'translate(' + [((d.source.x + d.target.x) / 2), ((d.source.y + d.target.y) / 2)] + ')rotate(' + angle + ')';
  });

注意我在tick事件上移动容器而不是实际的文本元素。

更新了小提琴:https://jsfiddle.net/reko91/wdouvab8/3/