SVG重新排序z-index(Raphael可选)


69

创建后如何重新排序Raphael或它们的基础SVG元素。更好的是,SVG中是否存在类似图层的内容?

理想情况下,我希望随时可以在其中放置元素的两层或多层;背景和前景层。如果这不是一种选择,则可以将元素弹出到前面是可以的,而在这种情况下将其推到后面会更好。

谢谢,


3
糟糕,Raphael甚至具有toFront和toBack方法。错过了我真傻。也感谢您在下面的回答,我仍然可能仍会使用它们
Miles

Answers:


95

给我密码!

// move element "on top of" all others within the same grouping
el.parentNode.appendChild(el); 

// move element "underneath" all others within the same grouping
el.parentNode.insertBefore(el,el.parentNode.firstChild);

// move element "on top of" all others in the entire document
el.ownerSVGElement.appendChild(el); 

// move element "underneath" all others in the entire document
el.ownerSVGElement.appendChild(el,el.ownerSVGElement.firstChild); 

特别是在Raphael中,使用toBack()和更容易toFront()

raphElement.toBack()  // Move this element below/behind all others
raphElement.toFront() // Move this element above/in front of all others

细节

SVG在绘制对象时使用“画家模型”:文档后面出现的项目是在文档前面出现的元素之后(顶部)绘制的。要更改项目的分层,必须使用appendChildinsertBefore类似方法对DOM中的元素重新排序。

您可以在此处查看此示例:http : //phrogz.net/SVG/drag_under_transformation.xhtml

  1. 拖动红色和蓝色对象,使其重叠。
  2. 单击每个对象,然后看它弹出到顶部。(但是,黄色圆圈始终总是可见的。)

此示例中元素的重新排序是通过源代码的第93/94行完成的:

el.addEventListener('mousedown',function(e){
  el.parentNode.appendChild(el); // move to top
  ...
},false);

当将鼠标向下推到某个元素上时,它将移动到其所有同级的最后一个元素上,从而使其在所有其他元素的“顶部”绘制。



4

SVG中没有z-index,代码后面的对象出现在第一个对象的上方。因此,根据您的需要,可以将节点移动到树的开头或树的结尾。

<g>(group)元素是svg中的通用容器,因此它们可以作为您的图层。只需在组之间移动节点即可实现所需的功能。


2
但是,如果我希望分层是与分组分开的独立概念,该怎么办?例如,我有两种身体部位形状,一种用于主体,另一种用于手臂。这两部分都包含两个单独的形状:一个用于笔触轮廓,另一个用于填充。它们需要这样分层:{手臂填充} {身体填充} {手臂笔划} {身体笔划},以使其相互啮合而不重叠其轮廓(轮廓需要平滑地勾勒出它们的轮廓)。但是我需要用手臂笔触对手臂填充进行分组,而将身体笔触对身体填充进行分组,以方便它们进行转换:/如何将分组与查看分开?
SasQ 2012年

0

如果预先定义了图形对象,则可以随着时间的流逝按不同的顺序对其进行分层:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1000 1000" width="400" height="400">
  <rect x="0" y="0" width="1000" height="1000" fill="black"/>
  <defs>
    <rect id="a1" x="0"   y="0"   width="500" height="500" fill="red"/>
    <rect id="a2" x="100" y="100" width="500" height="500" fill="blue"/>
  </defs>
  <g> 
    <use xlink:href="#a1"/>
    <use xlink:href="#a2"/>
    <set attributeName="visibility"  to="hidden" begin="2s"/> 
  </g>
  <g visibility="hidden"> 
    <use xlink:href="#a2"/>
    <use xlink:href="#a1"/>
    <set attributeName="visibility"  to="visible" begin="2s"/> 
  </g>
</svg>


-2

实际上,我认为单独的appendChild()会复制元素,而不仅仅是移动它。这可能不是问题,但是如果您想避免重复,我建议使用以下方法:

el.parentNode.appendChild(el.parentNode.removeChild(el));

2
不必要。appendChild移动,不复制节点。参见developer.mozilla.org/en-US/docs/Web/API/Node.appendChild
PaulGobée2014年

1
这个答案是错误的,应该删除。因为appendChild移动。
米歇尔

1
那你为什么不(或其他人)否决这个答案呢?
巴尔德(Balder)2016年

我投了反对票,但这对任何认为附加后复制元素然后阅读注释的人来说都是一个有用的答案。
2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.