我在我的项目中使用svg圆圈,像这样,

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120">
    <g>
        <g id="one">
            <circle fill="green" cx="100" cy="105" r="20" />
        </g>
        <g id="two">
            <circle fill="orange" cx="100" cy="95" r="20" />
        </g>
    </g>
</svg>

我在g标签中使用z索引来显示第一个元素。在我的项目中,我只需要使用z-index值,但我不能使用我的svg元素的z-index。我在谷歌上搜了很多,但没有找到相关的东西。 所以请帮助我在我的svg中使用z-index。

这里是DEMO。


当前回答

干净,快速,简单的解决方案张贴在这个答案的日期是不令人满意的。它们是基于SVG文档缺乏z顺序这一错误语句构建的。库也不是必需的。一行代码就可以执行大多数操作来操纵对象的z顺序或对象组,这可能是开发在x-y-z空间中移动2D对象的应用程序所需要的。

SVG文档片段中绝对存在Z顺序

所谓的SVG文档片段是派生自基本节点类型SVGElement的元素树。SVG文档片段的根节点是SVGSVGElement,它对应于HTML5 < SVG >标记。SVGGElement对应于<g>标记,并允许聚合子元素。

像在CSS中那样在SVGElement上使用z-index属性将会破坏SVG呈现模型。W3C SVG推荐v1.1第二版的3.3和3.4节指出,SVG文档片段(SVGSVGElement的子代树)是使用所谓的深度优先搜索树来呈现的。这个方案在任何意义上都是z阶的。

Z顺序实际上是一种计算机视觉的快捷方式,以避免对光线追踪的复杂性和计算需求的真正3D渲染的需求。SVG文档片段中元素的隐式z索引的线性方程。

z-index = z-index_of_svg_tag + depth_first_tree_index / tree_node_qty

这很重要,因为如果你想把一个在正方形下面的圆移动到它上面,你只需要把正方形插入到圆前面。这可以在JavaScript中轻松完成。

支持方法

SVGElement实例有两个方法支持简单的z顺序操作。

parent.removeChild(孩子) 的父母。方法(孩子,childRef)

不会造成混乱的正确答案

因为SVGGElement (<g>标记)可以像SVGCircleElement或任何其他形状一样轻松地删除和插入,所以可以使用SVGGElement轻松实现Adobe产品和其他图形工具的典型图像层。这个JavaScript实际上是一个Move Below命令。

parent.insertBefore(parent.removeChild(gRobot), gDoorway)

如果作为SVGGElement gRobot的子元素绘制的机器人层在作为SVGGElement g门口的子元素绘制的门口层之前,那么机器人现在在门口的后面,因为门口的z阶现在是1加上机器人的z阶。

“移动到上方”命令几乎同样简单。

parent.insertBefore(parent.removeChild(gRobot), gDoorway.nextSibling())

只要考虑a=a和b=b就能记住。

insert after = move above
insert before = move below

使DOM处于与视图一致的状态

这个答案是正确的,因为它是最小和完整的,并且像Adobe产品或其他设计良好的图形编辑器的内部一样,使内部表示处于与呈现所创建的视图一致的状态。

替代但有限的方法

另一种常用的方法是将CSS z-index与多个SVG文档片段(SVG标签)结合使用,除了底部的部分,其余部分的背景都是透明的。这再次破坏了SVG呈现模型的优雅性,使得在z顺序上向上或向下移动对象变得困难。


注:

(https://www.w3.org/TR/SVG/render.html v 1.1, 2nd Edition, 16 August 2011) 3.3 Rendering Order Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document fragment getting "painted" first. Subsequent elements are painted on top of previously painted elements. 3.4 How groups are rendered Grouping elements such as the ‘g’ element (see container elements) have the effect of producing a temporary separate canvas initialized to transparent black onto which child elements are painted. Upon the completion of the group, any filter effects specified for the group are applied to create a modified temporary canvas. The modified temporary canvas is composited into the background, taking into account any group-level masking and opacity settings on the group.

其他回答

正如其他人所说,z-index是由元素在DOM中出现的顺序定义的。如果手动重新排序你的html不是一个选项或将是困难的,你可以使用D3重新排序SVG组/对象。

使用D3更新DOM顺序和模仿Z-Index功能

使用D3更新SVG元素Z-Index

在最基本的级别上(如果您没有将id用于其他任何事情),您可以使用元素id作为z-index的替代品,并使用它们进行重新排序。除此之外,你几乎可以让你的想象力自由发挥。

代码片段中的示例

var circles = d3.selectAll('circle') var label = d3.select('svg').append('text') .attr('transform', 'translate(' + [5,100] + ')') var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }), yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }), radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } var setOrderBy = 'IDs'; var setOrder = d3.descending; label.text(setOrderBy); circles.data(zOrders[setOrderBy]) circles.sort(setOrder); <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 100"> <circle id="1" fill="green" cx="50" cy="40" r="20"/> <circle id="2" fill="orange" cx="60" cy="50" r="18"/> <circle id="3" fill="red" cx="40" cy="55" r="10"/> <circle id="4" fill="blue" cx="70" cy="20" r="30"/> <circle id="5" fill="pink" cx="35" cy="20" r="15"/> </svg>

基本思想是:

Use D3 to select the SVG DOM elements. var circles = d3.selectAll('circle') Create some array of z-indices with a 1:1 relationship with your SVG elements (that you want to reorder). Z-index arrays used in the examples below are IDs, x & y position, radii, etc.... var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }), yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }), radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } Then, use D3 to bind your z-indices to that selection. circles.data(zOrders[setOrderBy]); Lastly, call D3.sort to reorder the elements in the DOM based on the data. circles.sort(setOrder);


例子

可以按ID进行堆叠


最左边的SVG在上面


上面的半径最小


或者指定一个数组来为特定的顺序应用z-index——在我的示例代码中,数组[3,4,1,2,5]移动/重新排序第3个圆(在原始HTML顺序中),使其在DOM中处于第1位,第4位为第2位,第1位为第3位,以此类推……


这很容易做到:

克隆你的物品 对克隆项进行排序 替换克隆项

function rebuildElementsOrder( selector, orderAttr, sortFnCallback ) { let $items = $(selector); let $cloned = $items.clone(); $cloned.sort(sortFnCallback != null ? sortFnCallback : function(a,b) { let i0 = a.getAttribute(orderAttr)?parseInt(a.getAttribute(orderAttr)):0, i1 = b.getAttribute(orderAttr)?parseInt(b.getAttribute(orderAttr)):0; return i0 > i1?1:-1; }); $items.each(function(i, e){ e.replaceWith($cloned[i]); }) } $('use[order]').click(function() { rebuildElementsOrder('use[order]', 'order'); /* you can use z-index property for inline css declaration ** getComputedStyle always return "auto" in both Internal and External CSS decl [tested in chrome] rebuildElementsOrder( 'use[order]', null, function(a, b) { let i0 = a.style.zIndex?parseInt(a.style.zIndex):0, i1 = b.style.zIndex?parseInt(b.style.zIndex):0; return i0 > i1?1:-1; }); */ }); use[order] { cursor: pointer; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="keybContainer" viewBox="0 0 150 150" xml:space="preserve"> <defs> <symbol id="sym-cr" preserveAspectRatio="xMidYMid meet" viewBox="0 0 60 60"> <circle cx="30" cy="30" r="30" /> <text x="30" y="30" text-anchor="middle" font-size="0.45em" fill="white"> <tspan dy="0.2em">Click to reorder</tspan> </text> </symbol> </defs> <use order="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="0" y="0" width="60" height="60" style="fill: #ff9700; z-index: 1;"></use> <use order="4" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="50" y="20" width="50" height="50" style="fill: #0D47A1; z-index: 4;"></use> <use order="5" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="15" y="30" width="50" height="40" style="fill: #9E9E9E; z-index: 5;"></use> <use order="3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="25" y="30" width="80" height="80" style="fill: #D1E163; z-index: 3;"></use> <use order="2" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="30" y="0" width="50" height="70" style="fill: #00BCD4; z-index: 2;"></use> <use order="0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="5" y="5" width="100" height="100" style="fill: #E91E63; z-index: 0;"></use> </svg>

通过transform:TranslateZ移动到前面

警告:仅适用于FireFox

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" style="width:160px;身高:160 px;" > <g style=" font - family:宋体;"> <g id="one" style=" font - family:宋体;"> <circle fill="green" cx="100" cy="105" r="20" style="transform:TranslateZ(1px);" > < /圆> < / g > <g id="two" style=" font - family:宋体;"> <圆填充= "橙色"残雪= " 100 " cy = " 95 " r = " 20 " > < /圆> < / g > < / g > < / svg >

这是关于z-index和svg搜索的顶级谷歌结果。看完所有的答案后,有些答案很好,但我还是很困惑。

因此,对于像我这样的新手来说,这是目前的总结,9年后的2022年。

svg不能用z指数。

在svg中,z-index由元素在文档中出现的顺序定义。

如果你想要一些东西出现在顶部,或更接近用户,最后绘制或插入它之前。源

SVG 2可以支持z-index,但可能永远不会出现

SVG 2是一个实现这些功能和其他功能的提议,但它面临着永远无法向前发展的风险。

SVG 2于2016年进入候选推荐阶段,并于2018年进行了修订,最新草案于2021年6月8日发布。源

然而,它并没有得到很多的支持,很少有人在做这件事。所以不要屏住呼吸等这个消息。

你可以使用D3,但可能不应该

通常用于可视化数据的D3通过绑定你的z-index,然后排序来支持z-index,但它是一个大而复杂的库,如果你只是想让某个SVG出现在堆栈顶部,它可能不是最好的选择。

使用D3:

如果希望按顺序重新插入每个选定元素,将其作为其父元素的最后一个子元素。

selection.raise()