svg中 path 的路径命令

路径命令是对要绘制的路径的说明。每一个命令由代表命令的字母和代表参数的数字组成。

SVG 定义了六种路径命令类型,一共 20 条命令:

  • MoveTo(移动到):Mm
  • LineTo(画线至):LlHhV、`v
  • BezierCurve(贝塞尔曲线)
    • 二次贝塞尔曲线:QqTt
    • 三次贝塞尔曲线:CcSs
  • 椭圆曲线:Aa
  • ClosePath(封闭路径):Zz

本文主要是针对以上命令,进行整理

路径命令

先来看一下这一段 svg 代码,第一眼看上去是一脸懵逼状态,等我们梳理完,相信能对这段代码有一段非常非常清晰的认识和理解!

1
2
3
4
5
6
7
8
9
10
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path
fill="none"
stroke="red"
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30 z" />
</svg>

MoveTo(移动到)

MDN 文档解释

Moveto 指令可以被想象成拎起绘图笔,落脚到另一处。即,从当前位置Po; {xo, yo}),移动到新的位置Pn; {xn, yn}),且新的位置与 Po 之间不会绘制线段。

命令

  • M:(x, y)+

    当前位置移动到坐标 x,y。后续子坐标序列将被解释为隐式的绝对位置的 LineTo(L)命令的参数(见下方)。公式: Pn = {x, y}

  • m:(dx, dy)+

    当前位置沿 x 轴移动 dx,沿 y 轴移动 dy。后续子坐标序列将被解释为隐式的相对位置的 LineTo(l)命令的参数(见下方)。公式: Pn = {xo + dx, yo + dy}

简单来说

就是在一张白纸上,我们拿起笔,挪到了指定的位置上,注意,此时并不会产生线条,没有落笔。另外,大写字母命令是绝对位置坐标,小写字母命令是相对位置坐标

+号指的是可以是多个位置对,比如 M 10,30 20,30 40,50,可以方便不用多写几行 M 的命令

LineTo(画线至)

MDN 文档解释

Lineto 指令将绘制一条直线段。这个直线段从当前位置Po; {xo, yo})移到指定位置Pn; {xn, yn})。然后,指定位置Pn)将变成下一个命令中的当前位置Po′)。

命令

  • L:(x, y)+

    当前位置指定位置 x,y 之间绘制一条线段。后续子坐标序列将被解释为隐式的绝对位置的 LineTo(L)命令的参数。公式: Po′ = Pn = {x, y}

  • l:(dx, dy)+

    当前位置指定位置之间绘制一条线段,指定位置当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处。后续子坐标序列将被解释为隐式的相对位置的 LineTo(L)命令的参数。公式: Po′ = Pn = {xo + dx, yo + dy}

  • H:x+

    当前位置指定位置之间绘制一条水平线段。指定位置x 参数和当前位置y 坐标指定。后续子序列的值将被解释为隐式的绝对位置的 LineTo(H)命令的参数。公式: Po′ = Pn = {x, yo}

  • h:dx+

    当前位置指定位置之间绘制一条水平线段。指定位置当前位置沿 x 轴偏移 dxx 坐标和当前位置y 坐标指定。后续子序列的值将被解释为隐式的相对位置的 LineTo(h)命令的参数。公式: Po′ = Pn = {xo + dx, yo}

  • V:y+

    当前位置指定位置之间绘制一条垂直线段。指定位置y 参数和当前位置x 坐标指定。后续子序列的值将被解释为隐式的绝对位置的 LineTo(V)命令的参数。公式: Po′ = Pn = {xo, y}

  • v:dy+

    当前位置指定位置之间绘制一条垂直线段。指定位置当前位置沿 y 轴偏移 dyy 坐标和当前位置x 坐标指定。后续子序列的值将被解释为隐式的相对位置的 LineTo(v)命令的参数。公式: Po′ = Pn = {xo, yo + dy}

简单来说

在一张白纸上,我们拿起笔,找到指定的目标位置,然后拿一根尺子📏,连接目标位置和当前位置。此时因为落笔了,所以就会产生线条。

L语义化理解,就是 Line;H就是 Horizontal(水平的),水平方向移动;V就是 Vertical(垂直的),垂直方向移动

大小写命令和+,见 MoveTo 命令

BezierCurve(贝塞尔曲线)

n阶贝塞尔曲线需要有个 n-1个控制点(n >= 1)。

当 n =1 时,贝塞尔曲线只是一条两点之间的直线

关于贝塞尔曲线的推导公式,可以看参考资料下的维基百科内容,这里只讨论如何看懂贝塞尔曲线。

二次贝塞尔曲线

二次贝塞尔曲线是使用三个点定义的平滑曲线,它的控制点有 1 个:

123123

MDN 文档解释

  • 起始点(当前位置)

    P0> = {x0, y0}

  • 终点

    P1> = {x1, y1}

  • 控制点

    P2 = {x2, y2}(控制曲率)

命令

  • Q:(x1,y1, x,y)+

    当前位置终点 x,y 之间绘制一条二次贝塞尔曲线。控制点通过 x1,y1 指定。后续成对的坐标序列将被解释为隐式的绝对位置的二次贝塞尔曲线(Q)命令的参数。公式:Po′ = Pn = {x, y} ; Pc = {x1, y1}

  • q:(dx1,dy1, dx,dy)+

    当前位置终点终点当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条二次贝塞尔曲线。控制点当前位置(曲线的起始点)沿 x 轴偏移 dx1 以及沿 y 轴偏移 dy1 处。后续成对的坐标序列将被解释为隐式的相对位置的二次贝塞尔曲线(q)命令的参数。公式:Po′ = Pn = {xo + dx, yo + dy} ; Pc = {xo + dx1, yo + dy1}

  • T:(x,y)+

    当前位置终点 x,y 之间绘制一条平滑的二次贝塞尔曲线。控制点是上一条曲线命令的控制点当前位置上的反射点;若上一条命令不是曲线命令,则其与曲线的起始点(当前位置)相同。后续的坐标序列将被解释为隐式的绝对位置的平滑二次贝塞尔曲线(T)命令的参数。公式:Po′ = Pn = {x, y}

  • t:(dx,dy)+

    当前位置终点终点当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条平滑的二次贝塞尔曲线。控制点是上一条曲线命令的控制点当前位置上的反射点;若上一条命令不是曲线命令,则其与曲线的起始点(当前位置)相同。后续的坐标序列将被解释为隐式的相对位置的平滑二次贝塞尔曲线(t)命令的参数。公式:Po′ = Pn = {xo + dx, yo + dy}

简单来说

在一张白纸上,我们拿起笔,找到指定的目标位置,然后基于控制点来画一条曲线到目标点,并且到达目标点后当前节点改为新的起始点。

T是一个Q的快捷命令,一般用于画对称曲线,正弦、余弦曲线,具体就是:对上一条曲线命令的控制点当前位置上的反射点;若上一条命令不是曲线命令,则其与曲线的起始点(当前位置)相同。

大小写命令和+表达的意思,同样的,见 MoveTo 命令。

N次贝塞尔曲线

n次贝塞尔曲线则也可以联想出来,它受到了 n-1个控制点来控制。

由于高阶贝塞尔曲线没有命令,那这里以三次贝塞尔曲线为例。

同样的,配置和参数与二次贝塞尔曲线,基本一致,无非是增加了一个控制点的参数信息,还有就是命令标识符不一样了。以下是与二次贝塞尔曲线的对比:

二次贝塞尔曲线 三次贝塞尔曲线
命令 Q、q,T、t C、c,S、s
坐标对 2对坐标 3对坐标
目标坐标 最后1对是目标坐标 最后1对也是目标坐标

了解更多实例和参数信息,可以参考:三次贝塞尔曲线

椭圆曲线

MDN 文档解释

椭圆曲线是定义为椭圆的一部分的曲线。有时,使用椭圆曲线绘制高度规则的曲线会比使用贝塞尔曲线更容易。

命令

  • A:(rx ry angle large-arc-flag sweep-flag x y)+

    在当前位置和坐标 x,y 之间绘制一条椭圆曲线。 用于绘制圆弧的椭圆中心根据命令的其他参数确定:rxry 是椭圆的两个半径;angle 表示椭圆相对于 x 轴的旋转角度;large-arc-flagsweep-flag 允许选择必须绘制的弧线,因为其他参数可以绘制 4 条可能的弧线。large-arc-flag 允许选择一个大弧线(1)或一个小弧线(0),sweep-flag 允许选择一条顺时针旋转的弧线(1)或一条逆时针旋转的弧线(0)。坐标 x,y 将成为下一个命令中的当前位置。后续参数集合的序列将被解释为隐式的绝对位置的椭圆曲线(A)命令的参数。

  • a:(rx ry angle large-arc-flag sweep-flag dx dy)+

    在当前位置和指定位置之间绘制一条椭圆曲线。指定位置为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处。用于绘制圆弧的椭圆中心根据命令的其他参数确定:rxry 是椭圆的两个半径;angle 表示椭圆相对于 x 轴的旋转角度;large-arc-flagsweep-flag 允许选择必须绘制的弧线,因为其他参数可以绘制 4 条可能的弧线。large-arc-flag 允许选择一个大弧线(1)或一个小弧线(0),sweep-flag 允许选择一条顺时针旋转的弧线(1)或一条逆时针旋转的弧线(0)当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移后的位置将成为下一个命令中的当前位置。后续参数集合的序列将被解释为隐式的相对位置的椭圆曲线(a)命令的参数。

简单来说

主要是因为参数内容比较多,但是理解之后,会很简单。

首先是两个参数rx,ry,分别表示椭圆的两个半径。然后是 angle,表示椭圆相对于 x 轴的角度,顺时针旋转。

接下来的两个参数可能会让你回忆起来高中的数学知识了,如果没有这俩参数,那么再根据目标坐标参数,可以确定 4 条可能的弧线(高中时候接触过)。

因此我们需要确定具体哪一条曲线是我们想要的:

  • large-arc-flag 允许选择一个大弧线(1)或一个小弧线(0
  • sweep-flag 允许选择一条顺时针旋转的弧线(1)或一条逆时针旋转的弧线(0

然后就是目标坐标点了,目标坐标点是落在弧线上的,因此会出现椭圆并没有完全闭合的情况。

ClosePath(封闭路径)

MDN 文档解释

ClosePath 命令将从当前位置绘制一条直线到路径中的第一个点。

命令

  • Z,z

    通过连接路径的最后一个点与路径的起始点来闭合当前的子路径。如果这两个点的坐标不同,则在两者之间绘制一条直线。

备注: 使用 ClosePath 命令闭合的形状的外观可能与使用其他命令向起始点绘制一条线而闭合的形状不同,因为前者是将线条的末端连接在一起(根据 stroke-linejoin 的设置),而不是仅仅绘制到坐标点上。

参考资料

SVG可缩放矢量图形属性 d

维基百科-贝塞尔曲线