D3.js 仅更新已修改基础绑定数据的SVG元素

D3.js 仅更新已修改基础绑定数据的SVG元素,d3.js,D3.js,我有一个使用D3V4的力模拟图。每个节点都绑定到一些数据,例如,我使用这些数据来确定每个节点的半径 底层绑定数据会定期更新,对于某些节点,它会更改,而对于其他节点,它保持不变 我希望能够只选择绑定数据更改的那些DOM元素,以便在图形上突出显示这些元素 例如,假设最初我的数据(绑定到forceSimulation节点)为: 数据=[{id:1,类型:0},{id:2,类型:1}] 然后更新为: 数据=[{id:1,类型:1},{id:2,类型:1}] 我希望能够只选择对应于id=1的DOM

我有一个使用D3V4的力模拟图。每个节点都绑定到一些数据,例如,我使用这些数据来确定每个节点的半径

底层绑定数据会定期更新,对于某些节点,它会更改,而对于其他节点,它保持不变

我希望能够只选择绑定数据更改的那些DOM元素,以便在图形上突出显示这些元素

例如,假设最初我的数据(绑定到forceSimulation节点)为:

数据=[{id:1,类型:0},{id:2,类型:1}]
然后更新为:

数据=[{id:1,类型:1},{id:2,类型:1}]
我希望能够只选择对应于id=1的DOM元素,这样我就可以临时更改颜色

更新选择包含id=1和id=2-我可以维护以前数据值的内部映射并进行比较,但这似乎效率低下

谢谢,
Adam

如果可以检查单个数据属性以查看绑定的数据是否已更改,则一种方法是使用
selection.property
和自定义属性(如
type
)作为属性跟踪该属性。在附加数据时,可以相当轻松地定义属性:

  .append("circle")
  .property("type",function(d) { return d.type; });
然后,更新时,可以根据与属性匹配或不匹配的数据进行筛选:

  circles.data(newdata)
    .filter(function(d) {
      return d.type != d3.select(this).property("type")
    })
此筛选器将返回已更改其类型的元素。现在,我们可以重新分配属性以反映新类型并转换那些过滤的元素

下面的代码段应该说明这一点,数据只是一个数字1或2(用蓝色和橙色表示),用于设置属性类型。单击svg以更新数据,只有那些更改其基准的圆将临时更改其半径,同时更改其颜色以反映其新基准

var svg=d3.选择(“主体”)
.append(“svg”)
.attr(“宽度”,400)
.attr(“高度”,400);
var circles=svg.selectAll(“圆”)
.data(data())
.输入(“圆圈”)
.附加(“圆圈”)
.attr(“cy”,函数(d,i){
返回数学楼层(i/5)*40+20;
})
.attr(“cx”,函数(d,i){
返回i%5*40+20
})
.attr(“r”,8)
.attr(“填充”,函数(d){返回(d)-“钢蓝”:“橙色”})
.property(“type”,函数(d){return d;});
//点击更新:
打开(“单击”,函数(){
circles.data(data())
.过滤器(功能(d){
返回d!=d3.select(this).property(“type”)//过滤掉未更改的数据
})
.property(“type”,函数(d){return d;})//更新以反映新数据
.transition()
.attr(“r”,20)
.attr(“填充”、“深红色”)
.持续时间(500)
.transition()
.attr(“填充”,函数(d){返回(d)-“钢蓝”:“橙色”})
.attr(“r”,8)
.期限(500);
})
函数数据(){
var输出=[];
d3.范围(20).地图(功能(d){
output.push(Math.round(Math.random());
})
返回输出;
}
d3.local()
?第二个答案演示了一个可能的模型: