Javascript 我怎样才能用d3把一个圆圈带到前面?
首先,我使用d3.js在数组中显示不同大小的圆。在鼠标悬停时,我希望被鼠标悬停的圆圈变得更大,这是我可以做到的,但我不知道如何把它带到前面。当前,一旦渲染,它将隐藏在多个其他圆的后面。我怎样才能解决这个问题 下面是一个代码示例:Javascript 我怎样才能用d3把一个圆圈带到前面?,javascript,d3.js,visualization,Javascript,D3.js,Visualization,首先,我使用d3.js在数组中显示不同大小的圆。在鼠标悬停时,我希望被鼠标悬停的圆圈变得更大,这是我可以做到的,但我不知道如何把它带到前面。当前,一旦渲染,它将隐藏在多个其他圆的后面。我怎样才能解决这个问题 下面是一个代码示例: .on("mouseover", function() { d3.select(this).attr("r", function(d) { return 100; }) }) 我尝试使用排序和排序方法,但都不起作用。我很确定我做得不对。有什么想法吗
.on("mouseover", function() {
d3.select(this).attr("r", function(d) { return 100; })
})
我尝试使用排序和排序方法,但都不起作用。我很确定我做得不对。有什么想法吗?TL;DR
对于最新版本的D3,您可以使用selection.raise()
,如中所述。请向下滚动并向上投票
原始答案 您必须更改对象的顺序,并使鼠标移动过的圆成为添加的最后一个元素。正如您在这里所看到的:正如所建议的,您必须在主脚本之前定义以下内容:
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
然后,您只需在鼠标上方的对象上调用moveToFront
函数(比如圆圈
):
circles.on("mouseover",function(){
var sel = d3.select(this);
sel.moveToFront();
});
编辑:根据建议,需要使用.data()
的第二个参数将数据绑定到DOM。这对于不丢失对元素的绑定是必要的。请阅读Henrick的答案(并投票!)了解更多信息。一般建议,在将数据绑定到DOM时,始终使用.data()
的第二个参数,以充分利用d3的性能
编辑: 如所述,反向功能将是:
d3.selection.prototype.moveToBack = function() {
return this.each(function() {
var firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
如果使用
moveToFront()
方法,请确保为data()
join方法指定了第二个参数,否则数据将与DOM不同步
d3.js将数据(提供给parse()
)方法与您创建的DOM元素连接起来。如果按照上述建议操作DOM,d3.js将不知道哪个DOM元素对应于哪个数据“点”,除非在data()
调用中为每个数据“点”指定一个唯一的值,如下所示:
.data(数据,函数(d){return d.name;})
从我使用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;
}
}
});
})
从d3版本4开始,有一组内置函数可以处理这种类型的行为,而无需自己实现。有关更多信息,请参阅 长话短说,使用
selection.raise()
选择。提升()
按顺序重新插入每个选定元素作为其父元素的最后一个子元素。相当于:
选择。每个(函数(){
this.parentNode.appendChild(this);
})代码>
我对d3.js还是新手,但我认为您应该能够通过隐藏/显示元素来实现这一点,以便重新渲染它?从这篇文章来看,似乎将元素重新添加到svg具有这种效果。d3.selection.prototype.moveToFront=function(){返回this.each(function(){this.parentNode.appendChild(this);});};然后你可以说selection.moveToFront()。看看Ian如何在这个分支条目中使用这个方法:使用moveToFront方法。我也需要相反的方法:这就是我所做的:d3.selection.prototype.moveToBack=function(){返回这个。each(function(){var firstChild=this.parentNode.firstChild;if(firstChild){this.parentNode.insertBefore(this,firstChild);}}}}
请参见下面的@Henrik Nordberg答案。您的数据将不同步。hi@christopher Chiche,我在这里尝试了您的解决方案:但仍然无法更改线图的位置。想法?在IE中不起作用,如果节点上的其他事件处理程序被移动…它们会被删除。您能在这里详细说明一下吗?vi是什么“node”是svg元素的一个类吗?我在IEvis上遇到了同样的问题,它是D3选择的父元素,包含您要重新排序的元素。“node”是这些元素应该具有的CSS类。更简洁的排序函数:函数(a,b){s=selected.id;return(a.id==s)-(b.id==s);}
IE9的绝佳解决方案。如何从鼠标悬停事件外部获取对vis
的引用?我正在尝试在dragstart
事件内部找到vis
,但我在任何地方都找不到它。此
引用了我想带到顶部的元素。你能详细说明一下……要传递哪些数据吗?@DavidWilton better迟到了,我在我的答案中添加了对这个答案的引用。Mike已经涵盖了我们!!从v4.x开始,这是正确的方式。