代码之家  ›  专栏  ›  技术社区  ›  Corey Trager

使用JavaScript,我可以更改SVG<g>元素的Z索引/层吗?

  •  92
  • Corey Trager  · 技术社区  · 17 年前

    假设我有几个复合形状( <g> ).我希望能够单击并拖动它们,但我希望我现在碰巧拖动的那个在Z顺序上位于另一个之上,这样如果我将它拖动到另一个上面,另一个应该会黯然失色。

    9 回复  |  直到 11 年前
        1
  •  115
  •   Sam    17 年前

    SVG中的Z索引由元素在文档中出现的顺序定义(后续元素绘制在先前元素的顶部)。

    如果要将特定形状带到顶部,则必须更改元素顺序。

        2
  •  40
  •   Erik Dahlström    11 年前

    在树中移动元素的另一种方法是使用 <use> 您更改的元素 xlink:href 属性,以便它为您提供所需的z顺序。

    这是一个 old thread svg开发人员在邮件列表中讨论了这个主题,希望为一些形状设置动画。

    更新:

    <svg xmlns="http://www.w3.org/2000/svg" 
         xmlns:xlink="http://www.w3.org/1999/xlink"
         style="width:100%; height: 100%">
        <circle id="c1" cx="50" cy="50" r="40" fill="lime" />
        <rect id="r1" x="4" y="20" width="200" height="50" fill="cyan" />
        <circle id="c2" cx="70" cy="70" r="50" fill="fuchsia" />
        <use id="use" xlink:href="#c1" />
    </svg>
    

    在该示例中,<使用>元素是最后一个,这使它成为最前面的元素。我们可以选择任何其他元素作为最前面的元素,只需更改 xlink:href 属性。在上面的例子中,我们用 id="c1" ,这使其显示为最顶部的元素。

    看见 fiddle .

        3
  •  24
  •   CoR    14 年前

    这是一个老问题,但是。..

    在FireFox(7+)和Chrome(14+)上,您可以将svg_element拉到顶部。这不会给你完全控制z轴的自由,但总比什么都没有好;)

    只需再次附加该元素。

    var svg = doc.createElemNS('svg');
    var circle = doc.createElemNS('circle');
    var line = doc.createElemNS('line');
    
    svg.appendChild(circle); // appends it
    svg.appendChild(line);   // appends it over circle
    svg.appendChild(circle); // redraws it over line now
    

    我以为它会出错什么的。

    appendChild==替换自身==重绘

        4
  •  5
  •   Roman Rekhler    10 年前

    另一个未提及的解决方案是将每个svg项/项集放入div中。您可以轻松更改div的z-index。

    Fiddle: SVG elements cycles with z-index for containers

    …按下按钮将该元素“推”到前面。(与重新粉刷整套并将1个元素推到前面,但保持已接受解决方案中的原始顺序相反)

    有相对的z指数会很好。..

    stackOverflow想让我把代码放在jsfidle的链接上吗?…瞧

    var orderArray=[0,1,2];
    var divArray = document.querySelectorAll('.shape');
    var buttonArray = document.querySelectorAll('.button');
    
    for(var i=0;i<buttonArray.length;i++){
        buttonArray[i].onclick=function(){
            var localI = i;
            return function(){clickHandler(orderArray.indexOf(localI));};
        }();
    }
    
    
    function clickHandler(divIndex) {
         orderArray.push(orderArray.splice(divIndex, 1)[0]);
        orderDivs();
    }
    
    function orderDivs(){
        for(var i=0;i<orderArray.length;i++){
           divArray[orderArray[i]].style.zIndex=i;        
        }
    }
    svg {
        width: 100%;
        height: 100%;
        stroke: black;
        stroke-width:2px;
        pointer-events: all;
    }
    div{
        position:absolute;
    }
    div.button{
        top:55%;
        height:5%;
        width:15%;
        border-style: outset;
        cursor:pointer;
        text-align: center;
        background:rgb(175, 175, 234);
        
    }
    div.button:hover{
        border-style: inset;
        background:yellow;
        
    }
    div.button.first{
        left:0%;
    }
    div.button.second{
        left:20%;
    }
    div.button.third{
        left:40%;
    }
    <div class="shape">
        <svg>
        <circle cx="50" cy="50" r="40" fill="lime" />
        </svg>
    </div>
    <div class="shape">
        <svg>
            <rect x="4" y="20" width="200" height="50" fill="cyan" />
        </svg>
    </div>
    <div class="shape">
        <svg>
            <circle cx="70" cy="70" r="50" fill="fuchsia" />
        </svg>
    </div>
    
    <div class='button first'>lime</div>
    <div class='button second'>cyan</div>
    <div class='button third'>fuchsia</div>
        5
  •  5
  •   Patrick    6 年前

    是的,顺序指定了哪个对象将位于另一个对象之前。要操纵顺序,您需要在DOM中移动一些东西。SVG wiki上有一个很好的例子 https://www.w3.org/TR/SVG11/render.html#RenderingOrder

        6
  •  4
  •   Erel Segal-Halevi    10 年前

    如果你使用 svg.js library ,您可以使用“.front()”命令将任何元素移动到顶部。

        7
  •  3
  •   Ishank    12 年前

    亚当·布拉德利对萨姆的回答的评论完全切中要害。它使用jQuery而不是CSS,但他说:

    $('#thing-i-want-on-top').appendTo('#my-svg');
    

    然而,对于我正在创建的内容,我需要我的SVG路径在悬停时位于任何其他路径之上,但仍位于我的SVG文本之下。以下是我的想法:

    $('#thing-i-want-on-top').insertBefore('#id-for-svg-text');
    

    appendTo和insertBefore都会将元素移动到新位置,允许您随意更改SVG元素的深度。

        8
  •  3
  •   Pixel Rubble    9 年前

    SVG 使用渲染的“画家模型”。绘制在连续的操作中应用于输出设备,这样每个操作都会在输出设备的某个区域上绘制。当该区域与之前绘制的区域重叠时,新绘制会部分或完全遮挡旧绘制- link to this

        9
  •  3
  •   Agu Dondo    9 年前

    在SVG中,要获得更高的Z索引,您应该将元素在DOM树中向下移动。您可以使用jQuery完成此操作,选择SVG元素,将其删除并在所需位置再次附加:

    $('g.element').remove().appendTo('svg');