SVG/EPS(向量)如何用另一条路径剪裁一条路径?
How do SVG/EPS (vectors) clip a path by another path?
我试图了解 SVG 程序(如浏览器)如何通过给定路径绘制形状。我很难理解路径是如何绘制的,以及如何剪切形状的一部分。
例如,考虑带有顶环的字母 Å
和 A
。 SVG代码就像
<svg viewBox="0 0 1800 1800" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M426 822q0 -47 -24 -71.5t-80 -24.5q-104 0 -104 96q0 46 25.5 71t78.5 25q56 0 80 -25t24 -71z
M319 515h-1l-85 -264h169z
M374 822q0 51 -52 51q-50 0 -50 -51q0 -49 50 -49q52 0 52 49z
" />
</svg>
- 第一行:绘制
A
的正文。
- 第二行:画一个顶圆。
- 第三行:从第一行剪下一个三角形。
- 第四行:从第二行剪下一个小圆圈。
我的问题是:SVG 程序如何理解通过第二行绘制形状,但从现有形状剪裁形状?
显然答案是:如果路径在另一条路径内,则它会剪裁,否则会绘制。
我认为这不是全貌有两个原因:
- 查找一条路径是否在另一条路径内需要大量计算。
- 线条的顺序并不重要(剪切路径不一定在绘图路径之后)。
当然,这不仅限于 SVG,其他矢量格式如 EPS
也是如此。
要添加务实的观点,请将问题解读为:我们如何解析(在任何编程语言中)上述 d
元素以找出绘制的路径(黑色)上面 SVG 中给出的四个路径中的哪一个是剪裁(白色)?
一般来说,您根本不解析路径。
相反,您 'scan convert' 以当前分辨率将每条路径指向一系列矩形。每个 reactangle 可能低至一个像素高,并且在给定的 y 值处可能有多个矩形。
对要填充或描边的路径以及要应用为剪辑的路径执行此操作,然后与一系列矩形相交。显然,这是一项简单得多的任务。然后填充矩形。
当然,这确实会产生仅在给定分辨率下正确的结果。改变分辨率,你会得到一系列不同的矩形。然而,它以相当快的速度产生正确的输出。将两条任意路径相交产生一条新的任意路径显然是一项复杂得多的任务,为了绘制结果,我们不需要执行。
在接下来的示例中,我将在您的示例中使用字母 A 的路径。
在第一个 svg 元素中,字母 A 是从右到左绘制的,而孔是在相反方向绘制的:你得到 "clipping".
在第二个示例中,我反转了绘制孔的部分。现在这部分的绘制方向与字母A的主体部分相同。现在你不会得到"clipping"
在第三个示例中,我像以前一样使用反向路径,但我添加了 fill-rule="evenodd"
现在,由于 "fill-rule attribute is a presentation attribute defining the algorithm to use to determine the inside part of a shape".
,孔被剪掉了
svg{width:30%;border:solid}
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319 515h-1l-85 -264h169z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>
我试图了解 SVG 程序(如浏览器)如何通过给定路径绘制形状。我很难理解路径是如何绘制的,以及如何剪切形状的一部分。
例如,考虑带有顶环的字母 Å
和 A
。 SVG代码就像
<svg viewBox="0 0 1800 1800" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M426 822q0 -47 -24 -71.5t-80 -24.5q-104 0 -104 96q0 46 25.5 71t78.5 25q56 0 80 -25t24 -71z
M319 515h-1l-85 -264h169z
M374 822q0 51 -52 51q-50 0 -50 -51q0 -49 50 -49q52 0 52 49z
" />
</svg>
- 第一行:绘制
A
的正文。 - 第二行:画一个顶圆。
- 第三行:从第一行剪下一个三角形。
- 第四行:从第二行剪下一个小圆圈。
我的问题是:SVG 程序如何理解通过第二行绘制形状,但从现有形状剪裁形状?
显然答案是:如果路径在另一条路径内,则它会剪裁,否则会绘制。
我认为这不是全貌有两个原因:
- 查找一条路径是否在另一条路径内需要大量计算。
- 线条的顺序并不重要(剪切路径不一定在绘图路径之后)。
当然,这不仅限于 SVG,其他矢量格式如 EPS
也是如此。
要添加务实的观点,请将问题解读为:我们如何解析(在任何编程语言中)上述 d
元素以找出绘制的路径(黑色)上面 SVG 中给出的四个路径中的哪一个是剪裁(白色)?
一般来说,您根本不解析路径。
相反,您 'scan convert' 以当前分辨率将每条路径指向一系列矩形。每个 reactangle 可能低至一个像素高,并且在给定的 y 值处可能有多个矩形。
对要填充或描边的路径以及要应用为剪辑的路径执行此操作,然后与一系列矩形相交。显然,这是一项简单得多的任务。然后填充矩形。
当然,这确实会产生仅在给定分辨率下正确的结果。改变分辨率,你会得到一系列不同的矩形。然而,它以相当快的速度产生正确的输出。将两条任意路径相交产生一条新的任意路径显然是一项复杂得多的任务,为了绘制结果,我们不需要执行。
在接下来的示例中,我将在您的示例中使用字母 A 的路径。
在第一个 svg 元素中,字母 A 是从右到左绘制的,而孔是在相反方向绘制的:你得到 "clipping".
在第二个示例中,我反转了绘制孔的部分。现在这部分的绘制方向与字母A的主体部分相同。现在你不会得到"clipping"
在第三个示例中,我像以前一样使用反向路径,但我添加了 fill-rule="evenodd"
现在,由于 "fill-rule attribute is a presentation attribute defining the algorithm to use to determine the inside part of a shape".
svg{width:30%;border:solid}
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319 515h-1l-85 -264h169z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>