使用D3更新SVG元素Z-Index

Evi*_*key 75 javascript svg d3.js

使用D3库将SVG元素置于z顺序顶部的有效方法是什么?

我的特定情况是一个饼图其中突出(通过添加strokepath)当鼠标在给定的片.生成我的图表的代码块如下:

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);
    });
Run Code Online (Sandbox Code Playgroud)

我尝试过几个选项,但到目前为止还没有运气.使用style("z-index")和调用classed两者都不起作用.

"top"类在我的CSS中定义如下:

.top {
    fill: red;
    z-index: 100;
}
Run Code Online (Sandbox Code Playgroud)

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();
    });
Run Code Online (Sandbox Code Playgroud)

not*_*xit 85

正如其他答案中所解释的那样,SVG没有z-index的概念.相反,文档中元素的顺序决定了图形中的顺序.

除了手动重新排序元素外,还有另一种方法可用于某些情况:

使用D3时,您经常会遇到某些类型的元素,这些元素应始终在其他类型的元素之上绘制.

例如,在布置图形时,链接应始终位于节点下方.更一般地说,一些背景元素通常需要放在其他所有元素之下,而一些高光和叠加层应该放在上面.

如果您遇到这种情况,我发现为这些元素创建父组元素是最好的方法.在SVG中,您可以使用该g元素.例如,如果您的链接始终位于节点下方,请执行以下操作:

svg.append("g").attr("id", "links")
svg.append("g").attr("id", "nodes")
Run Code Online (Sandbox Code Playgroud)

现在,当您绘制链接和节点时,选择如下(选择器以#引用元素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
Run Code Online (Sandbox Code Playgroud)

现在,所有链接将始终在所有节点元素之前进行结构性附加.因此,SVG将显示所有节点下的所有链接,无论您添加或删除元素的频率和顺序如何.当然,相同类型的所有元素(即在同一容器内)仍将受其添加顺序的限制.


小智 49

开发人员提出的解决方案之一是:"使用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
  });
})
Run Code Online (Sandbox Code Playgroud)

  • 它对我也不起作用.a,b似乎只是数据,而不是d3选择元素或DOM元素 (3认同)

swe*_*edo 21

由于SVG没有Z-index但使用DOM元素的顺序,因此可以通过以下方式将其引入前面:

this.parentNode.appendChild(this);
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用insertBefore将其重新打开mouseout.但是,这要求您能够在之前插入元素的兄弟节点.

演示:看看这个JSFiddle


mee*_*mit 13

SVG doesn't do z-index. Z-order is dictated by the order of the SVG DOM elements in their container.

As far as I could tell (and I've tried this a couple of times in the past), D3 doesn't provide methods for detaching and reattaching a single element in order to bring it to the front or whatnot.

There is an .order() method, which reshuffles the nodes to match the order they appear in the selection. In your case, you need to bring a single element to the front. So, technically, you could resort the selection with the desired element in front (or at the end, can't remember which is topmost), and then call order() on it.

或者,您可以跳过d3执行此任务,并使用普通JS(或jQuery)重新插入该单个DOM元素.

  • 请注意,在某些浏览器中删除/插入鼠标悬停处理程序中的元素存在问题,这可能导致鼠标移除事件无法正常发送,因此我建议在所有浏览器中尝试此操作以确保其按预期工作. (5认同)

eva*_*jmg 6

简单的答案是使用d3排序方法.除了d3.select('g').order()之外,版本4中还有.lower()和.raise().这会改变元素的显示方式.有关更多信息,请参阅文档 - https://github.com/d3/d3/blob/master/API.md#selections-d3-selection