如何在基础数据更改时更新D3强制布局的元素

Ido*_*Ran 21 d3.js force-layout

我正在使用其中一个强制布局示例(http://bl.ocks.org/1153292)在我的网站上显示一个网络.

我允许用户在任何给定时间选择要查看的链接类型.我注意到当我选择查看链接类型A,然后添加链接类型B然后删除链接类型A时,类型B的剩余链接将显示A颜色.

这是运行以添加到svg图的链接的代码.我正在this.links通过添加和删除它的链接来更改阵列.正如您所看到的,我设置了class属性但它没有更新 - 它仍然是链接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 + ")"; });
Run Code Online (Sandbox Code Playgroud)

我目前通过更新tick函数内的class属性来解决这个问题,但这当然会导致很多不需要的工作.

我读到,enter操作返回已存在元素和新元素的合并选择,因此attr操作应更新存在元素并设置新元素.

我错过了什么?

Ido*_*Ran 19

在这篇文章中找到了答案

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();
Run Code Online (Sandbox Code Playgroud)

答案是我需要在selectAll.data的结果上调用attr运算符而不是在append运算符的结果上调用.

  • 该解决方案有效,因为cx和cy的attr更新不在enter()上下文中,因此它们每次都会发生.在原始代码中,attr函数在enter()上下文中被调用,因此它们仅根据对象标识创建一次.对我来说,了解关键函数是data()的第二个参数:http://bost.ocks.org/mike/constancy/ (3认同)