使用D3库将SVG元素置于z顺序的顶端的有效方法是什么?
我的特定场景是一个饼图,当鼠标悬停在给定的块上时,它会突出显示(通过向path
添加一个stroke
)。生成我的图表的代码块如下:
svg.selectAll("path")
.data(d)
.enter().append("path")
.attr("d", arc)
.attr("class", "arc")
.attr("fill", function(d) { return color(d.name); })
.attr("stroke", "#fff")
.attr("stroke-width", 0)
.on("mouseover", function(d) {
d3.select(this)
.attr("stroke-width", 2)
.classed("top", true);
//.style("z-index", 1);
})
.on("mouseout", function(d) {
d3.select(this)
.attr("stroke-width", 0)
.classed("top", false);
//.style("z-index", -1);
});
我试过几种方法,但到目前为止还没有成功。使用style("z-index")
和调用classed
都不起作用。
在我的CSS中,"top“类的定义如下:
.top {
fill: red;
z-index: 100;
}
fill
语句在那里是为了确保我知道它是正确打开/关闭的。它是。
我听说使用sort
是一种选择,但我不清楚如何实现它才能将“选定”元素置于首位。
更新:
我用下面的代码修复了我的特殊情况,它在mouseover
事件上向SVG添加了一个新的弧线,以显示高亮显示。
svg.selectAll("path")
.data(d)
.enter().append("path")
.attr("d", arc)
.attr("class", "arc")
.style("fill", function(d) { return color(d.name); })
.style("stroke", "#fff")
.style("stroke-width", 0)
.on("mouseover", function(d) {
svg.append("path")
.attr("d", d3.select(this).attr("d"))
.attr("id", "arcSelection")
.style("fill", "none")
.style("stroke", "#fff")
.style("stroke-width", 2);
})
.on("mouseout", function(d) {
d3.select("#arcSelection").remove();
});
发布于 2012-12-10 02:02:14
开发人员提出的解决方案之一是:“使用D3的排序操作符对元素进行重新排序。”(参见https://github.com/mbostock/d3/issues/252)
在这种情况下,可以通过比较元素的数据来对元素进行排序,如果元素是无数据元素,则可以比较位置:
.on("mouseover", function(d) {
svg.selectAll("path").sort(function (a, b) { // select the parent and sort the path's
if (a.id != d.id) return -1; // a is not the hovered element, send "a" to the back
else return 1; // a is the hovered element, bring "a" to the front
});
})
发布于 2013-06-16 12:14:49
正如在其他答案中所解释的,SVG没有z索引的概念。相反,文档中元素的顺序决定了绘图中的顺序。
除了手动重新排序元素之外,对于某些情况,还有另一种方法:
在使用D3时,您通常有某些类型的元素,这些元素应该始终绘制在其他类型的元素之上。
例如,在布局图形时,链接应始终放置在节点下方。更普遍的是,一些背景元素通常需要放在所有其他元素的下方,而一些高亮和叠加元素则应该放在上面。
如果您遇到这种情况,我发现为这些元素组创建父组元素是最好的方法。在SVG中,可以使用g
元素来实现这一点。例如,如果您具有应始终放置在节点下方的链接,请执行以下操作:
svg.append("g").attr("id", "links")
svg.append("g").attr("id", "nodes")
现在,当您绘制链接和节点时,选择如下所示(以#
开头的选择器引用元素id):
svg.select("#links").selectAll(".link")
// add data, attach elements and so on
svg.select("#nodes").selectAll(".node")
// add data, attach elements and so on
现在,所有链接在结构上总是附加在所有节点元素之前。因此,SVG将在所有节点下显示所有链接,无论您添加或删除元素的频率和顺序如何。当然,相同类型的所有元素(即在相同的容器中)仍将遵循添加它们的顺序。
发布于 2013-06-29 23:22:12
由于SVG没有Z-index,但使用了DOM元素的顺序,您可以通过以下方式将其放在前面:
this.parentNode.appendChild(this);
然后你可以利用insertBefore把它放回mouseout
上。然而,这要求您能够将您的元素插入之前的同级节点作为目标。
演示:查看此JSFiddle
https://stackoverflow.com/questions/13595175
复制