跳到主要内容

绘制顺序与层叠

SVG 默认是 文档序画家算法:后面的兄弟盖住前面的。这不是 Canvas 的 globalCompositeOperation 图层系统,也不是完整的 HTML 层叠上下文教科书——但 HTML 的 z-index / opacity / filter 会在 inline SVG 上制造新的合成层。

1. 文档序

<svg viewBox="0 0 200 200">
<rect width="200" height="200" fill="#eee"/>
<circle cx="80" cy="80" r="40" fill="crimson"/>
<circle cx="110" cy="110" r="40" fill="steelblue"/>
</svg>

钢蓝盖住绯红。要改叠放,移动 DOM 节点append / insertBefore),不要幻想有 ctx.restore 能把下面那层挖回来。

export function bringToFront(el: SVGElement): void {
el.parentNode?.append(el);
}

export function sendToBack(el: SVGElement): void {
const parent = el.parentNode;
if (!parent) return;
parent.insertBefore(el, parent.firstChild);
}

2. 组与隔离

&lt;g> 是变换和样式的作用域,不是 自动合成层。组上的 opacity: 0.5 会先把子树画在离屏缓冲再整体淡出——两个半透明圆重叠处不会「各 50% 叠成 75%」,而是整组 50%。这是设计师常踩的坑。

需要「每个子节点自己透明」时,透明度写在叶子上,不要写在组上。

isolation: isolatefiltermaskmix-blend-mode 同样可能逼出离屏层。性能见 滤镜合成层与重绘

3. z-index 能用,但不要当编辑器模型

inline SVG 在 HTML 文档里,子元素可以建层叠上下文。用 z-index 调装饰层可以,用它当图层系统会和「文档序 = 文件格式」冲突:序列化时 z-index 不一定写进 SVG 文件,另一端打开就乱。

生产编辑器:图层 = DOM 兄弟序(必要时外加 &lt;g data-layer>)。CSS z-index 只留给不进文件的 UI chrome。

4. display / visibility / pointer-events

属性渲染命中布局/包围盒
display: none不占渲染树;getCTM 可能为 null
visibility: hidden默认不命中仍占几何
opacity: 0看不见默认可命中仍占几何
pointer-events: none照常照常

隐藏但要占位的占位符用 visibility。彻底拆下用 display 或从树里 remove。透明遮罩坑:opacity: 0 的大 rect 会挡住下面的点击。

5. 失败形态

症状原因
导出后再打开图层全乱靠 CSS z-index 叠放,没改 DOM 序
组 fade 后重叠色不对opacity 写在 &lt;g> 上,整组先合成
点不到下面的节点上面有全屏透明 rect 或组级 pointer-events
getBBox 抛错或全 0元素 display: none 或不在文档里

权威资料

核对日期:2026-08-26