Quantcast
Channel: w3cplus
Viewing all articles
Browse latest Browse all 1557

SVG 基础——使用Curve指令创建路径

$
0
0

上周,我开始了关于路径的探讨,主要集中在使用不同的直线指令绘制各种直线和形状。今天我想要继续进行路径的探讨,谈谈可使用的不同的曲线指令。

曲线指令比直线指令需要解释的东西更多,所以我们马上开始吧。我会假设你已经阅读了上一篇关于直线指令的文章,如果你还没阅读,最好先去看那篇。

曲线指令

曲线指令一共有三组,和直线指令一样,指令字母大写表示坐标位置是绝对坐标,指令字母小写表示坐标位置是相对坐标。

  • 三次贝塞尔曲线指令 (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>

在这里,我添加了第二条贝塞尔曲线来连接第一条。你可以看到他们之间的衔接不是很平滑。

通常,在连接曲线时,第二条曲线的起点控制点是第一条曲线终点控制点的对称点。

幸运的是,你不必弄清楚如何计算控制点的反射。Ss指令是让浏览器帮你计算对称点的快捷方式,使用(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)。

二次贝塞尔曲线指令也有一个快捷方法,(Tt)指令可以用来平滑多条曲线之间的连接。它和三次贝塞尔曲线指令中的快捷方式(Ss)是同样的效果,也有助于通过对称的控制点来平滑地开始绘制第二条曲线。

<svg width="600" height="300">
  <path d="M100,200
           Q250,100 400,200
           T600 200"
    fill="none" stroke="#000" stroke-width="2px" />
</svg>

二次贝塞尔曲线指令是比较容易使用的,因为它只需要一个控制点。但是三次贝塞尔曲线指令有额外的控制点,所以可以提供更多的控制。

椭圆弧线

三种曲线指令中的最后一种是椭圆弧线(Aa)。下面这个弧线指令绘制了一段椭圆,它是曲线指令里边需要最多参数的,格式如下:

A rx ry  x-axis-rotation  large-arc-flag  sweep-flag  x y

这里

  • x,y是弧线的终点
  • rx是弧线在x轴方向的半径
  • ry是弧线在y轴方向的半径
  • x-axis-rotation是与x轴夹角的度数

椭圆弧绘制出的弧线是椭圆的一个片段。rxry的值相同,则绘制出圆

以下两个标志需要一些讲解。给定起点和终点坐标,以及rxryx-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-flagsweep-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/

彦子

在校学生,本科计算机专业。逗比一枚,热爱前端热爱生活,喜欢CSS喜欢JavaScript喜欢SVG,爱玩PS玩AI玩啊逗比的软件。努力向上,厚积薄发。

如需转载,烦请注明出处:http://www.w3cplus.com/svg/svg-paths-curve-commands.html


Viewing all articles
Browse latest Browse all 1557

Trending Articles