Javascript 我怎样才能用d3把一个圆圈带到前面?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14167863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I bring a circle to the front with d3?
提问by areke
First of all, I am using d3.js to display different sized circles in arrays. On mouse over, I want the circle being moused over to become bigger, which I can do, but I have no idea how to bring it to the front. Currently, once it's rendered, it's hidden behind multiple other circles. How can I fix this?
首先,我使用 d3.js 在数组中显示不同大小的圆圈。在鼠标悬停时,我希望被鼠标悬停的圆圈变大,我可以做到,但我不知道如何将它带到前面。目前,一旦它被渲染,它就会隐藏在多个其他圆圈后面。我怎样才能解决这个问题?
Here's a code sample:
这是一个代码示例:
.on("mouseover", function() {
d3.select(this).attr("r", function(d) { return 100; })
})
I tried using the sort and order methods, but they didn't work. I'm pretty sure i didn't do it correctly. Any thoughts?
我尝试使用 sort 和 order 方法,但它们不起作用。我很确定我没有做对。有什么想法吗?
回答by Christopher Chiche
You will have to change the order of object and make the circle you mouseover being the last element added. As you can see here: https://gist.github.com/3922684and as suggested by nautat, you have to define the following before your main script:
您将不得不更改对象的顺序并使鼠标悬停的圆圈成为添加的最后一个元素。正如您在此处看到的:https: //gist.github.com/3922684并按照nautat 的建议,您必须在主脚本之前定义以下内容:
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
Then you will just have to call the moveToFrontfunction on your object (say circles) on mouseover:
然后你只需要在鼠标悬停时调用moveToFront你的对象上的函数(比如circles):
circles.on("mouseover",function(){
var sel = d3.select(this);
sel.moveToFront();
});
Edit:As suggested by Henrik Nordbergit is necessary to bind the data to the DOM by using the second argument of the .data(). This is necessary to not lose binding on elements. Please read Henrick's answer (and upvote it!) for more info. As a general advice, always use the second argument of .data()when binding data to the DOM in order to leverage the full performance capabilities of d3.
编辑:正如Henrik Nordberg所建议的,有必要使用.data(). 这对于不失去对元素的约束是必要的。请阅读 Henrick 的回答(并点赞!)了解更多信息。作为一般建议,始终使用.data()when 将数据绑定到 DOM的第二个参数,以利用 d3 的全部性能功能。
Edit:As mentioned by Clemens Tolboom, the reverse function would be:
编辑:正如Clemens Tolboom所提到的,反向功能是:
d3.selection.prototype.moveToBack = function() {
return this.each(function() {
var firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
回答by Henrik Nordberg
If you use the moveToFront()method, make sure you are specifying the second argument to the data()join method, or your data will be out of synch with your DOM.
如果您使用该moveToFront()方法,请确保为data()join 方法指定第二个参数,否则您的数据将与您的 DOM 不同步。
d3.js joins your data (provided to a parse()) method with DOM elements you create. If you manipulate the DOM as proposed above, d3.js won't know what DOM element corresponds to what data 'point' unless you specify a unique value for each data 'point' in the data()call as the API referenceshows:
d3.js 将您的数据(提供给parse())方法与您创建的 DOM 元素连接起来。如果您按照上述建议操作 DOM,d3.js 将不知道什么 DOM 元素对应于什么数据“点”,除非您在data()调用中为每个数据“点”指定唯一值,如API 参考所示:
.data(data, function(d) { return d.name; })
.data(data, function(d) { return d.name; })
回答by tmpearce
As of d3 version 4, there are a set of built in functions that handle this type of behavior without needing to implement it yourself. See the d3v4 documentationfor more info.
从 d3 版本 4 开始,有一组内置函数可以处理此类行为,而无需自己实现。有关更多信息,请参阅d3v4 文档。
Long story short, to bring an element to the front, use selection.raise()
长话短说,要将元素放在前面,请使用 selection.raise()
selection.raise()
Re-inserts each selected element, in order, as the last child of its parent. Equivalent to:
selection.each(function() {this.parentNode.appendChild(this);});
selection.raise()
按顺序重新插入每个选定元素,作为其父元素的最后一个子元素。相当于:
selection.each(function() {this.parentNode.appendChild(this);});
回答by Ilya Boyandin
From my painful experience with IE9, using parentNode.appendChild may lead to lost event handlers in the nodes. So I tend to use another approach, that is, sorting the nodes so that the selected one is above the others:
根据我对 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;
}
}
});
})

