×

SVG基础 | SVG path 元素

作者:Terry2016.09.03来源:Web前端之家浏览:11910评论:0
关键词:html5SVG

SVG<path>元素用于定义一些复杂的图形。它可以结合使用直线,曲线等来制作各种不规则的图形。<path>元素是SVG基本图形中最为复杂的一个。要掌握和理解它也需要下一点苦工。

600.png

先来看一个例子:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M50,50
           A30,30 0 0,1 35,20
           L100,100
           M110,110
           L100,0"
        style="stroke:#660000; fill:none;"/>  
</svg>

上面代码的返回结果如下:

可以看到SVG图像中包含一条曲线和俩条直线,并且第二条直线是立刻第一条直线一段距离的。

所有的这些绘制工作都是在<path>元素中通过d属性来完成的。<d>属性包含了一些用于绘制的命令。在上面的例子中,M命令代表“Move to”(移动到)的意思。A命令代表一个“arc”(弧线)。L命令代表“Line”(直线)。这些命令都由一支“虚拟的画笔”来执行,这支笔可以移动和绘制图形。

设置和移动虚拟画笔

<path>元素的d属性中的第一个命令总是一个移动命令。在你绘制图形之前你必须移动虚拟画笔到某个位置上。移动画笔通过M指令来完成。看下面的例子:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M50,50"
          style="stroke:#660000; fill:none;"/>  
</svg>

上面的例子将虚拟画笔移动到(50,50)坐标的位置上。然后接下来的绘制命令将从这个位置开始绘制图形。

直线

直线命令是<path>元素最简单的命令。绘制直线使用Ll指令。下面是一个例子:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M50,50
             L100,100"
          style="stroke:#660000; fill:none;"/> 
</svg>

上面的例子从(50,50)坐标开始绘制一条直线,直线的终点在(100,100)的位置。下面是返回结果:

直线命令Ll有什么区别呢?大小的L指令绘制一条直线到一个绝度位置的点,而小写的l指令绘制一条直线到一个相对位置的点。相对位置的点是指从虚拟画笔开始绘制的点的坐标加上由l指令给出的坐标。看不懂?没关系,我们来举个例子:假如虚拟画笔开始绘制的位置是(50,50),l指令给出的坐标是(100,100),那么直线将从(50,50)位置开始绘制,绘制到(50+100,50+100)的位置。如果使用的是L100,100指令,那么就是从(50,50)位置开始绘制直线,绘制到(100,100)的位置。

路径图形总是从虚拟画笔的最后位置开始到新的坐标点绘制图形。每一个绘制命令都有一个结束点。在执行了这些绘制命令后,虚拟画笔会定位在这些命令所决定的结束点上。下一次的绘制命令将从这些点开始绘制。

弧线

使用<path>元素来绘制弧线使用Aa指令。大小和小写指令的意义与直线命令相同。看下面的例子:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M50,50
             A30,50 0 0,1 100,100"
          style="stroke:#660000; fill:none;"/> 
</svg>

上面代码的返回结果如下:

这个例子从(50,50)开始绘制弧线,结束点位置在(100,100)。

弧线的半径有A指令的两个数值决定。第一个参数是rx,水平方向上的半径,第二个参数是ry,垂直方向上的半径。如果rxry设置为相同的值,那么将得到一个圆形的弧线。rxry设置为不同的值将得到一个椭圆形的弧线。上面的例子中,rx的值为30,ry的值为50。

A指令上的第三个参数是x-axis-rotation。这个参数用于设置弧线X轴方向上的旋转。通常不需要改变这个参数,它的默认值为0。

第四和第五个参数分别为large-arc-flagsweep-flag。它们是两个标志位。我们知道,从A点到B点绘制一条弧线,可以得到两条不同的弧线。一条较大,另一条较小。large-arc-flag就是用于决定到底是绘制较大的那一条弧线还是绘制较小的那一条弧线。

下面来看一个例子,下面绘制4条相同的弧线,分别使用不同的large-arc-flagsweep-flag值:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M40,20  A30,30 0 0,0 70,70"
      style="stroke: #cccc00; stroke-width:2; fill:none;"/>

  <path d="M40,20  A30,30 0 1,0 70,70"
      style="stroke: #ff0000; stroke-width:2; fill:none;"/>

  <path d="M40,20  A30,30 0 1,1 70,70"
      style="stroke: #00ff00; stroke-width:2; fill:none;"/>

  <path d="M40,20  A30,30 0 0,1 70,70"
      style="stroke: #0000ff; stroke-width:2; fill:none;"/>
</svg>

先来看看结果:

4条不同的弧线都是从(40,20)绘制到(60,70)。它们的rxry值相等,因此是一个正圆圆弧。这4条弧线分别为一条长弧线,一条短弧线,还有两条是前面两条弧线的镜像。large-arc-flag属性决定是绘制长弧线还是短弧线。sweep-flag决定是否沿开始点到结束点的直线来镜像弧线。实际上,sweep-flag是控制弧线的绘制方向,顺时针或逆时针绘制弧线,得到的结果是一种“镜像”效果。

上面的代码绘制的第一条弧线是一条黄色的弧线。它的large-arc-flag属性设置为0,这意味着较小的弧线将被绘制。sweep-flag也被设置为0,这意味着不镜像弧线。黄色弧线的返回结果如下:

第二条被绘制的弧线是红色的弧线。它的large-arc-flag属性设置为1,这意味着较大的弧线将被绘制。sweep-flag属性设置为0,这意味着不镜像弧线。红色弧线的返回结果如下:

第三条被绘制的弧线是绿色的弧线。它是红色的弧线的一个镜像(沿弧线的开始点和结束点形成的直线做镜像)。可以看到它的sweep-flag属性被置为1。

第四条弧线是蓝色的弧线,它是黄色弧线的镜像,原因是它的sweep-flag属性被置为1。

贝兹曲线

使用<path>元素也可以绘制二次贝兹曲线。绘制二次贝兹曲线使用Qq命令。大小写版本的Q命令和直线的原理相同。大小版本的指令代表结束点位于绝对坐标系中。小写版本的的指令代表结束点位于相对坐标系中(相对于开始点)。下面是一个二次贝兹曲线的例子:

<path d="M50,50 Q50,100 100,100" 
      style="stroke: #006666; fill:none;"/>

它的返回结果如下:

上面的例子从(50,50)开始到(100,100)位置结束绘制一条二次贝兹曲线,控制点的位置在(50,100)的位置。控制点是由Q指令设置的两个参数。

如果你使用过一些矢量图像编辑软件,如Adobe Illustrator,那么你就会了解什么是贝兹曲线和控制点。在一个矢量图上的某个点,我们可以看到这个点上有两个控制手柄,通过拖拽这两个手柄可以调节这一点的弧度的大小。

控制点能够像磁铁一样拉伸曲线。控制点越接近弧线,弧线越平滑。控制点月远离弧线,弧线越被拉伸。下面是几个不同位置控制点的例子:

实际上,如果你从开始点绘制一条直线到控制点,在从控制点绘制一条直线到结束点,然后将这两条直线的中心点相连,那么这条连线正好和这条弧线相切。如下面的图像所示:

三次贝兹曲线

绘制三次贝兹曲线的命令是Cc。三次贝兹曲线和二次贝兹曲线相同,但是它有两个控制点。大写的命令的结束点使用绝对坐标系,小写的命令的结束点使用的是相对坐标系(相对于开始点)。下面是一个三次贝兹曲线的例子:

<path d="M50,50 C75,80 125,20 150,50"
      style="stroke: #006666; fill:none;"/>

下面是它的返回结果,另外还绘制了它的两个控制点。

你可以使用三次贝兹曲线来绘制一些复杂的曲线。下面是一些例子:

闭合路径

<path>元素有一个闭合路径的快捷命令。闭合路径是指从最后一个绘制点连线到开始点。这个命令是Z(或z,这里大小写没有区别)。下面是一个例子:

<path d="M50,50 L100,50 L100,100 Z"
    style="stroke: #006666; fill:none;"/>

下面是上面代码的返回结果:

结合使用各种命令

我们可以在<path>中集合使用各种绘制命令。下面是一个例子:

<path d="M100,100
         L150,100
         a50,25 0 0,0 150,100
         q50,-50 70,-170
         Z"
      style="stroke: #006666; fill: none;"/>

上面的代码绘制了一条直线,一条弧线和一条二次贝兹曲线,并且最后使用Z指令来闭合路径。得到的结果如下:

填充路径

我们可以使用CSS的fill属性来填充路径。看下面的例子:

<path d="M100,100 L150,100 L150,150  Z"
      style="stroke: #0000cc;
             stroke-width: 2px;
             fill  : #ccccff;"/>

上面代码得到的结果如下:

重复指令的简写方式

如果你重复多次连续使用同一个命令,可以可以将其省略,只写后面的参数即可。例如下面的例子:

<path d="M10,10   l100,0  0,50  -100,0  0,-50"
      style="stroke: #000000; fill:none;" />

在上面的例子中,多次连续使用了l指令来绘制直线,除了第一个l指令外,其他的都可以省略。得到的结果如下面所示:

path命令

在下面列出了SVG <path>元素的虚拟画笔可以使用的命令。大小的指令通常将参数坐标解析为绝对坐标。小写的指令通常将参数坐标解析为相对坐标。

指令参数名称描述
Mx,ymoveto移动虚拟画笔到指定的(x,y)坐标,仅移动不绘制
mx,ymoveto移动虚拟画笔到指定的(x,y)坐标,这个坐标是相对于当前画笔的坐标,仅移动不绘制
Lx,ylineto从当前画笔所在位置绘制一条直线到指定的(x,y)坐标
lx,ylineto从当前画笔所在位置绘制一条直线到指定的(x,y)坐标,(x,y)坐标是相对于花瓣位置的点
Hxhorizontal lineto绘制一条水平直线到参数指定的x坐标点,y坐标为画笔的y坐标
hxhorizontal lineto绘制一条水平直线到参数指定的x坐标点(当前x + 指定的x),x坐标相对于当前画笔x坐标
Vyvertical lineto从当前位置绘制一条垂直直线到参数指定的y坐标
vyhorizontal lineto从当前位置绘制一条垂直直线到参数指定的y坐标,y坐标相对于当前画笔的y坐标
Cx1,y1 x2,y2 x,ycurveto从当前画笔位置绘制一条三次贝兹曲线到参数(x,y)指定的坐标。x1,y1和x2,y2是曲线的开始和结束控制点,用于控制曲线的弧度
cx1,y1 x2,y2 x,ycurveto于大小C指令相同,但是坐标是相对于画笔的坐标
Sx2,y2 x,yshorthand / smooth curveto从当前画笔位置绘制一条三次贝兹曲线到参数(x,y)指定的坐标。x2,y2是结束控制点。开始控制点和前一条曲线的结束控制点相同
sx2,y2 x,yshorthand / smooth curveto和大小的S指令相同,但是坐标是相对于当前画笔的坐标点
Qx1,y1 x,y二次贝兹曲线从当前画笔位置绘制一条二次贝兹曲线到参数(x,y)指定的坐标。x1,y1是控制点,用于控制曲线的弧度
qx1,y1 x,y二次贝兹曲线和大小的Q指令相同,但是坐标是相对于当前画笔的坐标点
Tx,y平滑的二次贝兹曲线从当前画笔位置绘制一条二次贝兹曲线到参数(x,y)指定的坐标。控制点被假定为最后一次使用的控制点
tx,y平滑的二次贝兹曲线和大小的T指令相同,但是坐标是相对于当前画笔的坐标点
Arx,ry x-axis-rotation large-arc-flag,sweepflag x,y椭圆弧线从当前画笔位置开始绘制一条椭圆弧线到(x,y)指定的坐标。rx和ry分别为椭圆弧线水平和垂直方向上的半径。x-axis-rotation指定弧线绕x轴旋转的度数。它只在rx和ry的值不相同是有效果。large-arc-flag是大弧标志位,取值0或1,用于决定绘制大弧还是小弧。sweep-flag用于决定弧线绘制的方向
arx,ry x-axis-rotation large-arc-flag,sweepflag x,y椭圆弧线和大写的A指令相同,但是坐标是相对于当前画笔的坐标点
Z闭合路径从结束点绘制一条直线到开始点,闭合路径
z闭合路径从结束点绘制一条直线到开始点,闭合路径
返回SVG教程目录

相关阅读:

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/svg1472832000955.html

网友评论文明上网理性发言 已有0人参与

发表评论: