如何正确识别SVG path元素的孔洞与多形状及渲染规则
区分SVG Path中的独立形状与带孔洞形状的明确规则
嘿,我刚好之前做过SVG渲染相关的工作,这个问题其实核心是SVG的填充规则和子路径行为,我给你理清楚明确的判断规则:
核心逻辑:子路径 + 填充规则
首先要明确:每个M/m命令都会开启一个新的子路径,Z/z命令闭合当前子路径。单个<path>里的多个子路径,到底是独立形状还是带孔洞的单个形状,完全由填充规则和子路径的绘制方向决定。
1. 非零环绕数规则(默认规则,fill-rule="nonzero")
这是SVG默认的填充规则,判断逻辑是看路径环绕点的方向次数:
- 如果子路径的绘制方向(顺时针/逆时针)与外层路径相同,重叠区域会被填充,相当于叠加形状;
- 如果子路径方向与外层相反,重叠区域的环绕数会被抵消,形成孔洞。
举个例子:
<!-- 两个顺时针子路径:重叠的矩形,不是孔洞 --> <path d="M10 10 L90 10 L90 90 L10 90 Z M20 20 L80 20 L80 80 L20 80 Z" fill-rule="nonzero" /> <!-- 外顺时针+内逆时针:内部形成孔洞 --> <path d="M10 10 L90 10 L90 90 L10 90 Z M80 20 L20 20 L20 80 L80 80 Z" fill-rule="nonzero" />
2. 奇偶填充规则(fill-rule="evenodd")
这个规则更直观,不管子路径方向,只看点被多少个子路径包围:
- 被奇数个子路径包围 → 填充;
- 被偶数个子路径包围 → 不填充(形成孔洞)。
比如:
<!-- 不管子路径方向,内部区域被2个子路径包围(偶数),自动成为孔洞 --> <path d="M10 10 L90 10 L90 90 L10 90 Z M20 20 L80 20 L80 80 L20 80 Z" fill-rule="evenodd" />
关于路径组(<g>包含多个<path>)的情况
路径组里的每个<path>都是完全独立的形状,它们之间不会自动形成孔洞关系。哪怕多个<path>重叠,也只是简单的图层叠加,不会像单个<path>的子路径那样产生孔洞效果。如果要让组内路径形成孔洞,你需要用<clipPath>、<mask>这类蒙版机制,或者把这些路径合并成一个<path>的多个子路径。
快速判断步骤
- 先看当前
<path>的fill-rule属性(默认是nonzero); - 检查子路径的位置和方向:
- 子路径不重叠 → 必然是多个独立形状;
- 子路径重叠:
- 若用
nonzero规则:方向相反则是孔洞,方向相同则是重叠形状; - 若用
evenodd规则:偶数次包围的区域就是孔洞;
- 若用
- 路径组里的多个
<path>,直接按独立形状处理即可。
内容的提问来源于stack exchange,提问作者abcdef
相关产品推荐
相关产品推荐

