d3 enter()/merge()创建副本而不是更新 [英] d3 enter() / merge() creates copies instead of updating
问题描述
我正在使用D3.js(v4)构建交互式图形,其中每个父节点都有一组可折叠的子节点.因为我也想创建工具提示等,所以我用g
包裹了每个圆圈.我的代码的相关部分如下所示:
I'm building an interactive graph with D3.js (v4) where each parent node has a collapsible set of child nodes. Because I also want to create tooltips etc, I'm wrapping each circle with g
. Relevant part of my code looks like this:
var node = svg.append("g").selectAll(".node");
...
function update() {
nodes = getVisibleNodes()
...
node = node.data(nodes, function(d) { return d.name; });
node.exit().remove();
node = node.enter()
.append("g")
.classed("node", true)
.merge(node);
node
.append("circle")
.attr("r", function(d) { return d.size / 500; })
.on("click", click)
.on("contextmenu", rightclick)
.call(drag);
}
起初,一切似乎都工作正常,但是后来我注意到,每次运行update
时,都会显示/隐藏某些节点,新输入的节点会附加在旧节点的顶部.如果单击一会儿,最终每个g
中都会有几十个圆圈,一个在另一个上方绘制(当它们是半透明时很容易看到).
At first everything seems to work fine, but then I noticed that every time I run update
and some nodes are shown/hidden, new entering nodes are appended there on top of the old ones. If I click around for a while, I end up with tens of circles in each g
, drawn one on top of another (it's easily visible when they're semi-transparent).
我不太了解这里发生了什么,我在做什么错.对我有什么好的建议吗?
I don't really understand what's going on here, and what am I doing wrong. Any good advice for me?
推荐答案
仅浏览一下代码,我们就可以看到您为组选择了更新"/输入"/退出" >,但不适用于圆圈.
Just skimming through your code we can see that you have the "update"/"enter"/"exit" selections for the groups, but not for the circles.
因此,当一个组既不在输入"中也不在退出"中时,意味着它在更新"中,则您要在其上附加一个 new 圆圈每次您运行update
函数.
Therefore, when a group is neither in the "enter" nor in the "exit" selections, meaning that it is in the "update" selection, you're appending a new circle to it every time you run the update
function.
这是一个非常基本的演示.这是一个错误代码:data
这是一个随机数组,最多包含10个元素.但是,正如您所看到的,有时圆圈的数量远远超过10:
Here is a very basic demo to show it. This is a wrong code: data
here is a random array with 10 elements maximum. But, as you can see, sometimes the number of circles is way more than 10:
var svg = d3.select("svg");
d3.select("button").on("click", update);
var color = d3.scaleOrdinal(d3.schemeCategory20)
function update() {
var data = d3.range(~~(Math.random() * 10)).map(function(d) {
return {
size: ~~(Math.random() * 20),
x: ~~(Math.random() * 300),
y: ~~(Math.random() * 150)
}
})
var node = svg.selectAll(".node").data(data);
node.exit().remove();
node.enter()
.append("g")
.classed("node", true)
.merge(node)
.append("circle")
.attr("fill", function(d) {
return color(d.size)
})
.attr("r", function(d) {
return d.size;
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Update</button>
<br>
<svg></svg>
解决方案:
不要使用merge
,请分开输入和更新组的选择.并且,在更新选择中,选择现有圈子.
Don't use merge
, separate your enter and update selections for the groups. And, in the update selection, select existing circles.
node.select("circle")
.attr("r", etc...
以下是正确代码的演示,它的圈数不得超过10个:
Here is the demo of a correct code, it never has more than 10 circles:
var svg = d3.select("svg");
d3.select("button").on("click", update);
var color = d3.scaleOrdinal(d3.schemeCategory20)
function update() {
var data = d3.range(~~(Math.random() * 10)).map(function(d) {
return {
size: ~~(Math.random() * 20),
x: ~~(Math.random() * 300),
y: ~~(Math.random() * 150)
}
})
var node = svg.selectAll(".node").data(data);
node.exit().remove();
node.enter()
.append("g")
.classed("node", true)
.append("circle")
.attr("fill", function(d) {
return color(d.size)
})
.attr("r", function(d) {
return d.size;
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
node.select("circle")
.transition()
.duration(1000)
.attr("fill", function(d) {
return color(d.size)
})
.attr("r", function(d) {
return d.size;
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Update</button>
<br>
<svg></svg>
这篇关于d3 enter()/merge()创建副本而不是更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!