截至本答案发布之日,干净,快速,简便的解决方案并不令人满意。它们是根据SVG文档缺少z顺序的有缺陷的语句构建的。图书馆也不是必需的。一行代码可执行大多数操作,以操纵在xyz空间中移动2D对象的应用程序的开发中可能需要的z个对象或对象组的顺序。
SVG文档片段中绝对存在Z顺序
所谓的SVG文档片段是从基本节点类型SVGElement派生的元素树。SVG文档片段的根节点是SVGSVGElement,它对应于HTML5 <svg>标签。SVGGElement对应于<g>标签,并允许聚合子级。
在CSS中,在SVGElement上具有z-index属性会破坏SVG渲染模型。W3C SVG Recommendation v1.1 2nd Edition的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(孩子)
- parent.insertBefore(child,childRef)
不会造成混乱的正确答案
由于可以像SVGCircleElement或其他任何形状一样轻松地移除和插入SVGGElement(<g>标记),因此可以使用SVGGElement轻松实现Adobe产品和其他图形工具的典型图像层。该JavaScript本质上是“ 移至下方”命令。
parent.insertBefore(parent.removeChild(gRobot), gDoorway)
如果绘制为SVGGElement gRobot的子代的机器人的层位于绘制为SVGGElement gDoorway的子代的门口之前,则该机器人现在位于门口后面,因为门口的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,第二版,2011年8月16日)
3.3渲染顺序SVG文档片段中的元素具有隐式的绘制顺序,SVG文档片段中的第一个元素首先被“绘制”。后续元素被绘制在先前绘制的元素之上。
3.4如何呈现组诸如“ g”元素(请参见容器元素)之类的分组元素具有产生临时的单独画布的作用,该画布被初始化为透明的黑色,并在上面绘制了子元素。组完成后,将为该组指定的所有滤镜效果都将应用以创建修改后的临时画布。修改后的临时画布会组合到背景中,同时考虑到该组上的任何组级别的遮罩和不透明度设置。