我正在制作一个动态图表,通过更新图表上相应圆圈的位置和大小来显示某些数据点的开发(类似于https://bost.ocks.org/mike/nations/)。
由于圆圈可以重叠,我需要在顶部绘制最小的圆圈。
在示例中,这是通过调用selection.sort()
来完成的,但如果我这样做(使用较新的D3v4),我会收到意外行为。排序似乎切换与可视圆对象关联的数据对象。
检查这个小提琴看。按原样运行一次(不在第45行调用sort(order)
) - 这是预期的行为。每个对象的y值都不会改变,因此圆圈应该在水平线上移动。现在取消注释第45行以在每次更新时调用排序并再次运行它。这次圆圈的路径突然交叉(因为底层物体被切换)。
https://jsfiddle.net/orj1rcy8/1/
API声明selection.sort() Returns a new selection that contains a copy ...
。我认为这是问题所在,但是我现在不明白正确的方法会是什么样子。
答案 0 :(得分:2)
简短回答
绑定数据时需要一个关键功能:
.data(dataForKey(keyIndex), function(d){ return d.name})
这是您更新的小提琴:https://jsfiddle.net/7kyvzkwe/
答案很长
这里发生的事情是你是我们称之为对象恒定性的受害者,或者更确切地说,没有正确设置对象的持久性(这里是一个很好的阅读,由{{3编写) }})。
问题是,在D3中,数据按顺序绑定到元素:
如果未指定键功能,则数据中的第一个数据将分配给第一个选定元素,第二个数据分配给第二个选定元素,依此类推。
所以,让我们看看发生了什么。您的代码按顺序有三个圆圈:
数据附加在上述顺序中。但是,当你sort(order)
时:
function order(a, b){
return radius(b) - radius(a);
}
您对元素进行排序,现在您已经:
然后出现问题:下次运行next
函数并绑定新数据时,您将数据绑定到新订单中的DOM元素。也就是说,关于最小圆的数据被绑定到DOM中的最大圆。使用元素的名称,您将有关item1
的数据绑定到DOM中的item3
(假设您有3个元素,则唯一一个始终接收正确数据的是item2
)。
你可以在下一个小提琴中更好地理解这一点。在下一个小提琴中,我正在使用您的代码,取消注释sort
函数。但是,与原始代码不同,这里我改变了数据的顺序,所以我们先得到最大的圆,然后是中等,然后是最小的圆:
[{name:"item1", x:1, y:2, z:15},
{name:"item2", x:1, y:4, z:10},
{name:"item3", x:1, y:6, z:3}];
你可以看到,即使打电话给sort
,圈子也会留在他们的位置。这是小提琴:Mike Bostock
这是因为下次运行函数next
时,最小圆的数据被绑定到最小的圆(在DOM中),依此类推......
因此,简而言之,如果要保持对象的持久性,则需要键函数。一个https://jsfiddle.net/9p1tL43j/:
...可以指定控制将哪个数据分配给哪个元素,替换默认的join-by-index。