上周,我开始了关于路径的探讨,主要集中在使用不同的直线指令绘制各种直线和形状。今天我想要继续进行路径的探讨,谈谈可使用的不同的曲线指令。
曲线指令比直线指令需要解释的东西更多,所以我们马上开始吧。我会假设你已经阅读了上一篇关于直线指令的文章,如果你还没阅读,最好先去看那篇。
曲线指令
曲线指令一共有三组,和直线指令一样,指令字母大写表示坐标位置是绝对坐标,指令字母小写表示坐标位置是相对坐标。
- 三次贝塞尔曲线指令 (C, c, S, s)
- 二次贝塞尔曲线指令 (Q, q, T, t)
- 椭圆弧线 (A, a)
三次贝塞尔曲线指令
我会假设你已经对贝塞尔曲线很熟悉,可能你已经在某些图形编辑器里绘制过。我就不解释他们的数学原理了,但是你可以通过定义一个起点和终点,以及两个控制点(一个控制起点,一个控制终点),绘制一条贝塞尔曲线。
三次贝塞尔曲线指令的格式为:
C (or c) x1,y1 x2,y2 x,y
这里
x1
,y1
是曲线起点的控制点坐标x2
,y2
是曲线终点的控制点坐标x
,y
是曲线的终点坐标
曲线的起点是上一条指令的终点,所以我们不需要再次设置。
举个例子吧,我会像之前一样,所有的示例都使用内联SVG。
<svg width="600" height="300">
<path d="M100,200
C100,100 400,100 400,200"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
我从一个SVG元素开始,给它设置宽度和高度值,还有一个填充以及描边。希望你现在对这几个属性都已经很熟悉。
路径从点(100,200
)开始,这也是曲线的起点。三次贝塞尔曲线指令(C
)绘制曲线,第一个控制点的坐标是(100,100
),第二个控制点是(400,100
)。终点坐标是(400,200
)。
曲线从第一个控制点的方向开始,然后转弯,再根据第二个控制点的方向到达曲线终点。
查看贝塞尔曲线指令就知道绘制的结果,这对我来说不容易,我猜想你也是同样的感觉。你可能需要自己去做一些试验,尝试设置不同的控制点的值,来得到一个更好的印象。当然我也需要。
像直线一样,你不需要只用一条曲线就结束绘制。你可以把曲线一条一条连接起来然后创建更复杂的曲线。
<svg width="600" height="300">
<path d="M100,200 C100,100 400,100 400,200 c100,200 400,100 300,0" fill="none" stroke="#000" stroke-width="2px" />
</svg>
在这里,我添加了第二条贝塞尔曲线来连接第一条。你可以看到他们之间的衔接不是很平滑。
通常,在连接曲线时,第二条曲线的起点控制点是第一条曲线终点控制点的对称点。
幸运的是,你不必弄清楚如何计算控制点的反射。S
和 s
指令是让浏览器帮你计算对称点的快捷方式,使用(S s
)指令创建对称的控制点很容易。
<svg width="600" height="300">
<path d="M100,200
C100,100 400,100 400,200
s100,100 300,0"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
在这里我用了一个相对定位的指令(s
)快捷地创建了第二条曲线,来匹配使用相对坐标的曲线。你可以看到两条曲线连接的交点处相比之前平滑了很多。
这里是另外的两条曲线,这次使用的是绝对定位的指令(S
)的快捷方式。
<svg width="600" height="300">
<path d="M100,200
C100,100 400,100 400,200
S400,100 300,0"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
他们看起来完全不一样,即使两条曲线之间的连接还是很平滑。接合的地方可能不平浅,但也是平滑的。你再绘制一条独立的曲线就能明白我的意思,只不过这次第二条曲线使用的是绝对定位的曲线。
<svg width="600" height="300">
<path d="M100,200
C100,100 400,100 400,200
C100,200 400,100 300,0"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
如果你的曲线不能按照你想象的绘制出来,可能是因为你绝对定位和相对定位使用颠倒了。
二次贝塞尔曲线指令
你的直觉可能会告诉你,二次贝塞尔曲线指令会更复杂,还添加了一个额外的控制点。但是恰恰相反。
二次贝塞尔曲线指令只需要一个控制点,同时作为起点控制点和终点控制点。
<svg width="600" height="300">
<path d="M100,200
Q250,100 400,200"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
我们还是使用moveto
指令作为开始,绘制二次贝塞尔曲线。曲线的起点坐标是(100,200
),终点坐标是(400,200
),控制点坐标是(250,100
)。
二次贝塞尔曲线指令也有一个快捷方法,(T
或 t
)指令可以用来平滑多条曲线之间的连接。它和三次贝塞尔曲线指令中的快捷方式(S
或 s
)是同样的效果,也有助于通过对称的控制点来平滑地开始绘制第二条曲线。
<svg width="600" height="300">
<path d="M100,200
Q250,100 400,200
T600 200"
fill="none" stroke="#000" stroke-width="2px" />
</svg>
二次贝塞尔曲线指令是比较容易使用的,因为它只需要一个控制点。但是三次贝塞尔曲线指令有额外的控制点,所以可以提供更多的控制。
椭圆弧线
三种曲线指令中的最后一种是椭圆弧线(A
或 a
)。下面这个弧线指令绘制了一段椭圆,它是曲线指令里边需要最多参数的,格式如下:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
这里
x
,y
是弧线的终点rx
是弧线在x
轴方向的半径ry
是弧线在y
轴方向的半径x-axis-rotation
是与x
轴夹角的度数
椭圆弧绘制出的弧线是椭圆的一个片段。若rx
和ry
的值相同,则绘制出圆。
以下两个标志需要一些讲解。给定起点和终点坐标,以及rx
ry
x-axis-rotation
的值,绘制出的弧线有四种可能,用下边的示例看起来比较清晰。
<svg width="600" height="300">
<path d="M250,100 A120,80 0 0,0 250,200"
fill="none" stroke="red" stroke-width="5" />
<path d="M250,100 A120,80 0 1,1 250,200"
fill="none" stroke="green" stroke-width="5"/>
<path d="M250,100 A120,80 0 1,0 250,200"
fill="none" stroke="purple" stroke-width="5"/>
<path d="M250,100 A120,80 0 0,1 250,200"
fill="none" stroke="blue" stroke-width="5"/>
</svg>
示例中,看起来好像有两个相同尺寸的彩色椭圆,但是这其实是四段不同的弧线,具体参考上方的代码。
在四段弧线连接处的这两个点分别是起点(上)和终点(下),这三个椭圆都有相同的rx
, ry
, x-axis-rotation
值。正如你看到的这四段不同的弧线,分别都是从起点绘制到终点。
这四段弧线的区别是 large-arc-flag
和 sweep-flag
参数的值。图中的红色和紫色弧线,sweep-flag
的值都为0
,红色弧线 large-arc-flag
的值为0
,而紫色弧线 large-arc-flag
的值为1
。它们的区别仅在于 large-arc-flag
值的不同。
对比这两段圆弧,你能猜出 large-arc-flag
值是用来干嘛的吗?值为0
表示使用较小的弧线,值为1
表示使用较大的弧线。
现在比较一下红色和蓝色弧线。这两段弧线的 large-arc-flag
值都为0
,所以它们都是较小的弧线。但是红色弧线还有一个 sweep-flag
值为0
,而蓝色的 sweep-flag
值为1
。
蓝色弧线和红色弧线是关于起点和终点所在的坐标轴对称的。 sweep-flag
的值决定了是使用弧线(值为0
)还是使用它的轴对称弧线(值为1
)。
我刚才做了几个示例来理解不同的弧线和标志(flags)。如果你还是不清楚弧线中的各种参数的意义,不要担心。复制我的代码去做几个试验,改变一些值来看看结果。多实践才能进步。
总结思考
正如我在上周的文章里边提到的,路径比基本形状更强大、更灵活。使用它们绘制图形可能比较繁琐,但是并不会很多。甚至有些时候用使用它们来绘制图形要更简单。它们不单单可以用来创建直线、曲线和图形,还有更多其它的用途,我们先保留着,下次再探讨。
奇怪的是,很多可以创建SVG图像的图形编辑器会导出使用路径的图像,所以理解和学习如何使用路径是很有意义的,即使你通常都不使用代码绘制路径。
路径有两组指令,一组用来创建直线,一组用来创建曲线。记住这些指令以及使用它来绘制图像花不了几分钟的,你可能会觉得直线比曲线更容易使用,但是多做一些练习,曲线也是很容易上手的。
这阵子我可能会把SVG系列的文章暂时搁置,接下来的几个月我会回来编写更多SVG主题的文章,但是五个星期之后我们可能会讲一点SVG之外的内容。
本文根据@Steven Bradley的《SVG Basics—Creating Paths With Curve Commands》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.vanseodesign.com/web-design/svg-paths-curve-commands/。
如需转载,烦请注明出处:http://www.w3cplus.com/svg/svg-paths-curve-commands.html