如何在SVG元素中使用z-index?

242

我在我的项目中使用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-index来显示元素。在我的项目中,我只需要使用z-index值,但我无法将z-index用于我的svg元素。我已经进行了大量的谷歌搜索,但没有找到相关的内容。

请帮助我在我的svg中使用z-index。

这是演示。


18个回答

5

4
我们已经到了2019年,但是SVG仍然不支持z-index。您可以在Mozilla的SVG2支持网站上看到z-index的状态为“未实现”。同时,您也可以在Bug 360148 "Support the 'z-index' property on SVG elements"(报告时间:12年前)中查看相关信息。
但是,在SVG中有3种设置它的可能性:
  1. 使用element.appendChild(aChild);
  2. 使用parentNode.insertBefore(newNode, referenceNode);
  3. 使用targetElement.insertAdjacentElement(positionStr, newElement);(IE不支持SVG)

交互演示示例

使用这三个函数即可。

var state = 0,
    index = 100;

document.onclick = function(e)
{
    if(e.target.getAttribute('class') == 'clickable')
    {
        var parent = e.target.parentNode;

        if(state == 0)
            parent.appendChild(e.target);
        else if(state == 1)
            parent.insertBefore(e.target, null); //null - adds it on the end
        else if(state == 2)
            parent.insertAdjacentElement('beforeend', e.target);
        else
            e.target.style.zIndex = index++;
    }
};

if(!document.querySelector('svg').insertAdjacentElement)
{
    var label = document.querySelectorAll('label')[2];
    label.setAttribute('disabled','disabled');
    label.style.color = '#aaa';
    label.style.background = '#eee';
    label.style.cursor = 'not-allowed';
    label.title = 'This function is not supported in SVG for your browser.';
}
label{background:#cef;padding:5px;cursor:pointer}
.clickable{cursor:pointer}
With: 
<label><input type="radio" name="check" onclick="state=0" checked/>appendChild()</label>
<label><input type="radio" name="check" onclick="state=1"/>insertBefore()</label><br><br>
<label><input type="radio" name="check" onclick="state=2"/>insertAdjacentElement()</label>
<label><input type="radio" name="check" onclick="state=3"/>Try it with z-index</label>
<br>
<svg width="150" height="150" viewBox="0 0 150 150">
    <g stroke="none">
        <rect id="i1" class="clickable" x="10" y="10" width="50" height="50" fill="#80f"/>
        <rect id="i2" class="clickable" x="40" y="40" width="50" height="50" fill="#8f0"/>
        <rect id="i3" class="clickable" x="70" y="70" width="50" height="50" fill="#08f"/>
    </g>
</svg>


3

将SVG元素推到最后,这样它的z-index就会在顶部。在SVG中,没有叫做z-index的属性。尝试使用以下JavaScript将元素带到顶部。

var Target = document.getElementById(event.currentTarget.id);
var svg = document.getElementById("SVGEditor");
svg.insertBefore(Target, svg.lastChild.nextSibling);

目标:是我们需要置顶的元素 svg:是元素的容器


2

通过 transform:TranslateZ 将元素移动到最前面

警告:仅适用于 FireFox 浏览器

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" style="width:160px; height:160px;">
    <g style="transform-style: preserve-3d;">
        <g id="one" style="transform-style: preserve-3d;">
            <circle fill="green" cx="100" cy="105" r="20" style="transform:TranslateZ(1px);"></circle>
        </g>
        <g id="two" style="transform-style: preserve-3d;">
            <circle fill="orange" cx="100" cy="95" r="20"></circle>
        </g>
    </g>
</svg>


这里对我不起作用。橙色的覆盖了绿色的。 - krave
@krave:使用什么浏览器? - Robert Máslo
Chrome 最新版本 - krave
@krave:你说得对。只在FireFox中有效。我很抱歉。 - Robert Máslo

1
我使用过的更好的use示例。
<svg>
  <defs>
    <circle id="one" fill="green" cx="40" cy="40" r="20" /> 
    <circle id="two" fill="orange" cx="50" cy="40" r="20"/> 
  </defs>
  <use href="#two" />
  <use href="#one" />
</svg>

要控制顺序,您可以更改这些use元素的href属性值。这对于动画非常有用。

由于defs,圆形元素仅绘制一次。

jsfiddle.net/7msv2w5d


0

我想分享一个小技巧,当你想把一个特定的元素放在最上面时,可以使用这个方法。

function moveInFront(element) {
    const svg = element.closest('svg'); // Find the parent SVG
    svg.appendChild(element); // Append child moves the element to the end
}

这个方法可行,因为引用文档中说: "appendChild() 将 [元素] 从当前位置移动到新位置" 而不是添加一个副本。

注意:如果该元素嵌套在其他元素中,您需要将该元素移动到组内的前面,并可能需要将整个组移到最前面。


0

这很容易实现:

  1. 克隆你的项目
  2. 排序克隆的项目
  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>


-1

use 可以用于此目的,但是使用 use 放置的元素很难操作... 我使用后无法弄清楚的是:为什么我不能悬停在 use 元素上(无论是鼠标悬停还是 js 中的 mouseover、mouseenter 操作都不起作用),以获得其他功能 - 比如显示圆圈上的文本。 之后我回到了 圆圈重新排序,因为那是唯一可以操作这些 svg 对象的方式。


不好意思,但这听起来像是一个AI / Bot生成的答案。OP的问题甚至没有使用任何svg <use>元素,而您的答案也没有提到任何z-index解决方法。 - herrstrietzel
当前您的回答写得不够清晰,请 [编辑] 添加更多细节以帮助他人理解如何解决问题。您可以在帮助中心中找到有关编写良好答案的更多信息。 - Community
抱歉...我的英语不如你的好...<use>是z-index的解决方法,如果不清楚的话,但它有缺点,因为在svg中很难操作元素-这就是我想说的...并且只提到它是因为我花了几天时间尝试在元素悬停/单击时放置附加信息,但没有成功,之后我使用了<use>,只是为了在我的svg中具有z-index效果。最后,我重新排列了代码,以绘制元素的顺序,使得可以看到应该覆盖所有其他元素的元素位于顶部。 - ievaws

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接