首先,我使用d3.js在数组中显示不同大小的圆圈。鼠标悬停时,我希望将鼠标悬空变大,这是我可以做的,但我不知道如何把它带到前面。目前,一旦渲染,它就隐藏在多个其他圈子后面。我该如何解决这个问题?
以下是代码示例:
.on("mouseover", function() {
d3.select(this).attr("r", function(d) { return 100; })
})
我尝试使用排序和顺序方法,但它们不起作用。我很确定我没有正确地做到这一点。有什么想法吗?
答案 0 :(得分:115)
您必须更改对象的顺序,并使鼠标悬停的圆圈成为添加的最后一个元素。正如您在此处看到的那样:https://gist.github.com/3922684并且正如nautat所建议的那样,您必须在主脚本之前定义以下内容:
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
然后,您只需在鼠标悬停时调用对象上的moveToFront
函数(例如circles
):
circles.on("mouseover",function(){
var sel = d3.select(this);
sel.moveToFront();
});
编辑:正如Henrik Nordberg所建议的那样,必须使用.data()
的第二个参数将数据绑定到DOM。这对于不失去对元素的约束是必要的。请阅读Henrick的答案(并进行投票!)了解更多信息。作为一般建议,在将数据绑定到DOM时,请始终使用.data()
的第二个参数,以便充分利用d3的完整性能。
修改强> 正如Clemens Tolboom所提到的,反向函数将是:
d3.selection.prototype.moveToBack = function() {
this.each(function() {
this.parentNode.firstChild
&& this.parentNode.insertBefore(this, firstChild);
}
});
};
答案 1 :(得分:21)
如果您使用moveToFront()
方法,请确保指定data()
连接方法的第二个参数,否则您的数据将与DOM不同步。
d3.js使用您创建的DOM元素加入您的数据(提供给parse()
)方法。如果您按照上面的建议操纵DOM,除非您为data()
调用中的每个数据“点”指定唯一值.data(data, function(d) { return d.name; })
,否则d3.js将不知道哪个DOM元素对应于哪个数据'点'。 3}}显示:
{{1}}
答案 2 :(得分:15)
从d3版本4开始,有一组内置函数可以处理这种类型的行为,而无需自己实现。有关详细信息,请参阅d3v4 documentation。
长话短说,要将元素添加到前面,请使用selection.raise()
selection.raise()
按顺序重新插入每个选定的元素,作为其父元素的最后一个子元素。相当于:
selection.each(function() {
this.parentNode.appendChild(this);
});
答案 3 :(得分:13)
根据我对IE9的痛苦经历,使用parentNode.appendChild可能会导致节点中的事件处理程序丢失。所以我倾向于使用另一种方法,即对节点进行排序,使所选节点高于其他节点:
.on("mouseover", function(selected) {
vis.selectAll('.node')
.sort(function(a, b) {
if (a.id === selected.id) {
return 1;
} else {
if (b.id === selected.id) {
return -1;
} else {
return 0;
}
}
});
})