如何在 svg 元素中使用 z 索引?

2022-08-30 01:04:28

我在我的项目中使用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>

我在标签中使用 z 索引来显示第一个元素。在我的项目中,我只需要使用z索引值,但我不能对我的svg元素使用z索引。我已经谷歌了很多,但我没有找到任何相对的东西。所以请帮我在我的svg中使用z索引。g

这是演示。


答案 1

规范

在 SVG 规范版本 1.1 中,呈现顺序基于文档顺序:

first element -> "painted" first

参考 SVG 1.1。规范

3.3 渲染顺序

SVG 文档片段中的元素具有隐式绘制顺序,SVG 文档片段中的第一个元素首先“绘制”。后续元素绘制在先前绘制的元素之上。


解决方案(清洁速度更快)

您应该将绿色圆圈作为要绘制的最新对象。因此,请交换这两个元素。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120"> 
   <!-- First draw the orange circle -->
   <circle fill="orange" cx="100" cy="95" r="20"/> 

   <!-- Then draw the green circle over the current canvas -->
   <circle fill="green" cx="100" cy="105" r="20"/> 
</svg>

这是你的jsFiddle的分叉。

解决方案(替代)

具有属性(仅适用于 SVG 2)的标记,并且作为值表示元素的 id。请记住,即使结果看起来很好,这也可能不是最佳解决方案。有一点时间,这里是SVG 1.1规范“使用”元素的链接。usexlink:hrefhref

目的:

避免要求作者修改引用的文档以向根元素添加 ID。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120">
    <!-- First draw the green circle -->
    <circle id="one" fill="green" cx="100" cy="105" r="20" />
    
    <!-- Then draw the orange circle over the current canvas -->
    <circle id="two" fill="orange" cx="100" cy="95" r="20" />
    
    <!-- Finally draw again the green circle over the current canvas -->
    <use xlink:href="#one"/>
</svg>

关于 SVG 2 的说明

SVG 2 规范是下一个主要版本,仍然支持上述功能。

3.4. 渲染顺序

SVG 中的元素以三维形式定位。除了它们在 SVG 视区的 x 轴和 y 轴上的位置外,SVG 元素也位于 z 轴上。z 轴上的位置定义了它们的绘制顺序

沿 z 轴,元素被分组到堆叠上下文中。

3.4.1. 在 SVG 中建立堆叠上下文

...

堆叠上下文是概念工具,用于描述在呈现文档时必须将元素一个接一个地绘制的顺序,...


答案 2

正如这里的其他人所说,z索引是由元素在DOM中出现的顺序定义的。如果手动重新排序 html 不是一个选项或很困难,则可以使用 D3 对 SVG 组/对象进行重新排序。

使用 D3 更新 DOM 顺序和模拟 Z 索引功能

使用 D3 更新 SVG 元素 Z 索引

在最基本的级别(如果您没有将 ID 用于其他任何内容),则可以使用元素 ID 作为 z 索引的替代项,并随这些 ID 重新排序。除此之外,你几乎可以让你的想象力疯狂。

代码片段中的示例

var circles = d3.selectAll('circle')
var label = d3.select('svg').append('text')
    .attr('transform', 'translate(' + [5,100] + ')')

var zOrders = {
    IDs: circles[0].map(function(cv){ return cv.id; }),
    xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
    yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
    radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
    customOrder: [3, 4, 1, 2, 5]
}

var setOrderBy = 'IDs';
var setOrder = d3.descending;

label.text(setOrderBy);
circles.data(zOrders[setOrderBy])
circles.sort(setOrder);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 100"> 
  <circle id="1" fill="green" cx="50" cy="40" r="20"/> 
  <circle id="2" fill="orange" cx="60" cy="50" r="18"/>
  <circle id="3" fill="red" cx="40" cy="55" r="10"/> 
  <circle id="4" fill="blue" cx="70" cy="20" r="30"/> 
  <circle id="5" fill="pink" cx="35" cy="20" r="15"/> 
</svg>

基本思想是:

  1. 使用 D3 选择 SVG DOM 元素。

    var circles = d3.selectAll('circle')
    
  2. 创建一些与 SVG 元素(要重新排序)具有 1:1 关系的 z 索引数组。以下示例中使用的 Z 索引数组是 ID、x 和 y 位置、半径等。

    var zOrders = {
        IDs: circles[0].map(function(cv){ return cv.id; }),
        xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }),
        yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }),
        radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }),
        customOrder: [3, 4, 1, 2, 5]
    }
    
  3. 然后,使用 D3 将 z 索引绑定到该选择。

    circles.data(zOrders[setOrderBy]);
    
  4. 最后,调用 D3.sort 以根据数据对 DOM 中的元素重新排序。

    circles.sort(setOrder);
    

例子

enter image description here

  • 您可以按 ID 堆叠

enter image description here

  • 最左边的 SVG 位于顶部

enter image description here

  • 顶部最小半径

enter image description here

  • 或者指定一个数组来为特定排序应用 z 索引 - 在我的示例代码中,数组移动/重新排序第 3 个圆圈(以原始 HTML 顺序)在 DOM 中为 1st,第 4 个为 2nd,1st 为 3rd,依此类推...[3,4,1,2,5]