Javascript 我怎样才能用d3把一个圆圈带到前面?

Javascript 我怎样才能用d3把一个圆圈带到前面?,javascript,d3.js,visualization,Javascript,D3.js,Visualization,首先,我使用d3.js在数组中显示不同大小的圆。在鼠标悬停时,我希望被鼠标悬停的圆圈变得更大,这是我可以做到的,但我不知道如何把它带到前面。当前,一旦渲染,它将隐藏在多个其他圆的后面。我怎样才能解决这个问题 下面是一个代码示例: .on("mouseover", function() { d3.select(this).attr("r", function(d) { return 100; }) }) 我尝试使用排序和排序方法,但都不起作用。我很确定我做得不对。有什么想法吗

首先,我使用d3.js在数组中显示不同大小的圆。在鼠标悬停时,我希望被鼠标悬停的圆圈变得更大,这是我可以做到的,但我不知道如何把它带到前面。当前,一旦渲染,它将隐藏在多个其他圆的后面。我怎样才能解决这个问题

下面是一个代码示例:

   .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开始,这是正确的方式。