88

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

4

9 回答 9

117

SVG 中的 Z 索引由元素在文档中出现的顺序定义。如果要将特定形状置于顶部,则必须更改元素顺序。

于 2009-01-27T02:27:58.590 回答
40

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

这是 svg-developers 邮件列表上的一个旧线程,在想要为某些形状设置动画的背景下讨论这个主题。

更新:

<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>

在此示例中,<use> 元素是最后一个元素,这使其成为最前面的元素。xlink:href我们可以通过更改属性选择任何其他元素作为最前面的元素。在上面的示例中,我们选择了带有 的圆圈id="c1",这使其显示为最顶部的元素。

小提琴

于 2011-06-09T08:03:13.897 回答
25

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

在 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 == 替换自身 == 重绘

于 2011-11-07T23:46:50.537 回答
5

是的,顺序是指定什么对象将在另一个对象前面。要操作顺序,您需要移动有关 DOM 的内容。SVG wiki 上有一个很好的例子,网址为https://www.w3.org/TR/SVG11/render.html#RenderingOrder

于 2009-01-27T02:49:08.517 回答
5

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

小提琴:SVG元素循环与容器的z-index

...按下按钮将该元素“推”到前面。(与重新绘制整个集合并将 1 个元素推到前面,但保持原始顺序与接受的解决方案一样)

拥有相对 z 索引会非常好......

如果它是来自 jsfiddle 的链接,stackOverflow 想让我把代码放在里面吗?......好

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>

于 2015-03-06T17:49:15.193 回答
4

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

于 2015-03-13T12:15:44.787 回答
4

亚当布拉德利对山姆回答的评论完全正确。它只使用 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 元素的深度。

于 2016-08-26T11:54:48.240 回答
3

SVG使用“画家模型”进行渲染。绘画在连续操作中应用于输出设备,以便每个操作在输出设备的某个区域上绘画。当该区域与先前绘制的区域重叠时,新油漆会部分或完全遮盖旧油漆。-链接到此

于 2014-01-16T13:03:03.670 回答
3

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

$('g.element').remove().appendTo('svg');
于 2016-10-04T21:00:36.537 回答