本文转自:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Pathshtml
<path>
元素是SVG基本形状中最强大的一个,它不只能建立其余基本形状,还能建立更多其余形状。编辑器
另外,path只须要设定不多的点,就能够建立平滑流畅的线条(好比曲线)。虽然polyline元素也能实现相似的效果,可是必须设置大量的点 (点越密集,越接近连续,看起来越平滑流畅),而且这种作法不可以放大(放大后,点的离散更明显)。为了更好的理解path,你最好用path实际画一个 SVG图形,虽然用XML或文本编辑器来编辑path元素不是很容易,但能够帮助咱们理解path是如何工做的,因此,你就忍了吧。svg
上一章提到过,path元素的形状是经过d属性
定义的,d属性
的值是一个“命令+参数”的序列,咱们将学习这些命令,而且看到不少相关的示例。性能
每个命令都用一个关键字母来表示,好比,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点。跟在命令字母后面的,是你须要移动到的那个点的x和y轴坐标。好比移动到 (10,10)这个点的命令,应该写成“M 10 10”。这一段字符结束后,解析器就会去读下一段命令。每个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另外一种是用小写字母,表示采用相对定位(例如:从上一个点开始,向上移动10px,向左移动7px)。学习
d属性
采用的是用户坐标系统,不需标明单位。在后面的教程中,咱们会学到如何让变换path,以知足更多需求。动画
<path>
元素有5个画直线的命令,如名字所示,直线命令就是在两个点之间画直线。首先是“Move to”命令,M,前面已经提到过,它有两个参数,分别是须要移动到的点的x轴和y轴的坐标。假设,你的画笔当前位于一个点,在使用M命令移动画笔后,只会 移动画笔,但不会在两点之间画线。由于M命令仅仅是移动画笔,但不画线。因此M命令常常出如今路径的开始处,用来指明从何处开始画。spa
M x y
or翻译
m dx dy
这有一个比较好的例子,不过咱们没画任何东西,只是将画笔移动到路径的起点,因此咱们不会看到任何图案。可是,我把咱们移动到的点标注出来了,因此 在下面的例子里会看到(10,10)坐标上有一个点。注意,若是只画path,这里什么都不会显示。(这段不太好理解,说明一下:为了更好地展现路径,下 面的全部例子里,在用path绘制路径的同时,也会用circle标注路径上的点。)code
<?xml version="1.0" standalone="no"?> <svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10"/> <!-- Points --> <circle cx="10" cy="10" r="2" fill="red"/> </svg>
可以真正画出线的命令有3个(M命令是移动画笔位置,可是不画线),最经常使用的是“Line to”命令,L
,L
有两个参数,分别是一个点的x轴和y轴坐标,L命令将会在该点和当前点(L前面画笔所在的点)之间画一条线段。xml
L x y (or l dx dy)
另外还有两个简写命令,用来绘制平行线和垂直线。H
,绘制平行线。V
,绘制垂直线。它们都只带一个参数,标明在x轴或y轴移动到的位置,由于它们都只在一个坐标轴的方向上移动。
H x (or h dx) V y (or v dy)
如今咱们已经掌握了一些命令,能够开始画一些东西了。先从简单的地方开始,画一个简单的矩形(一样的效果用<rect/>
元素能够更简单的实现),矩形是由水平线和垂直线组成的,因此这个例子能够很好地展示前面讲的画线的方法。
<?xml version="1.0" standalone="no"?> <svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10 H 90 V 90 H 10 L 10 10"/> <!-- Points --> <circle cx="10" cy="10" r="2" fill="red"/> <circle cx="90" cy="90" r="2" fill="red"/> <circle cx="90" cy="10" r="2" fill="red"/> <circle cx="10" cy="90" r="2" fill="red"/> </svg>
最后,咱们能够经过一个“闭合路径命令”Z来简化上面的path,Z
命令会从当前点画一条直线到路径的起点,尽管咱们不老是须要闭合路径,可是它仍是常常被放到路径的最后。另外,Z命令不用区分大小写。
Z (or z)
因此上面例子里用到的路径,能够简化成这样:
<path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/>
你也可使用这些命令的相对坐标形式来绘制相同的图形,如以前所述,相对命令使用的是小写字母,它们的参数不是指定一个明确的坐标,而是表示相对于它前面的点须要移动多少距离。例如前面的示例,画的是一个80*80的正方形,用相对命令能够这样描述:
<path d="M10 10 h 80 v 80 h -80 Z" fill="transparent" stroke="black"/>
上述路径是:画笔移动到(10,10)点,由此开始,向右移动80像素构成一条水平线,而后向下移动80像素,而后向左移动80像素,而后再回到起点。
你可能会问这些命令有什么用,由于 <polygon>
和 <polyline>
能够作到画出同样的图形。答案是,这些命令能够作得更多。若是你只是画直线,那么其余元素可能会更好用,可是,path倒是众多开发者在SVG绘制中惯用 的。据我所知,它们之间不存在性能上的优劣。可是经过脚本生成path可能有所不一样,由于另外两种方法只须要指明点,而path在这方面的语法会更复杂一 些。
绘制平滑曲线的命令有3个,其中两个用来绘制贝塞尔曲线,另一个用来绘制弧形或者说是圆的一部分。若是你用过Inkscape, Illustrator 或者 Photoshop,你可能对贝塞尔曲线有必定程度的了解。关于贝塞尔曲线的数学解释,你能够在Wikipedia的文档中获取到。其中的不少知识均可以用在这里。贝塞尔曲线的类型有不少,可是在path元素里,只存在两种:三次贝塞尔曲线C,和二次贝塞尔曲线Q。
咱们从稍微复杂一点的三次贝塞尔曲线入手,三次贝塞尔曲线须要定义一个点和两个控制点,因此用C命令建立三次贝塞尔曲线,须要设置三组坐标参数:
C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)
这里的最后一个坐标(x,y)表示的是曲线的终点,另外两个坐标是控制点,(x1,y1)是起点的控制点,(x2,y2)是终点的控制点。若是你熟 悉代数或者微积分的话,会更容易理解控制点,控制点描述的是曲线起始点的斜率,曲线上各个点的斜率,是从起点斜率到终点斜率的渐变过程。(文字描述很差, 维基百科上有图示,更直观。)
<?xml version="1.0" standalone="no"?> <svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/> <path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/> <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="transparent"/> <path d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent"/> <path d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent"/> <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="transparent"/> <path d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/> <path d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="transparent"/> <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/> </svg>
上面的例子里,建立了9个三次贝塞尔曲线。有一点比较遗憾,标记控制点的代码会比较庞大,因此在这里舍弃了。(以前全部点都用circle标记,此 处同样,只不过没把代码列出来)。若是你想更准确地控制它们,能够本身动手把他们画出来。图例上的曲线从左开始,控制点在水平方向上逐渐分开,最右侧的曲 线,控制点之间离得更远。这里要注意观察,曲线沿着起点到第一控制点的方向伸出,逐渐弯曲,而后沿着第二控制点到终点的方向结束。(这个翻译的不太好,没 弄清原文想要表达的意思。曲线的原理,仍是看维基百科比较好。)
你能够将若干个贝塞尔曲线连起来,从而建立出一条很长的平滑曲线。若是将一个点的控制点在它的另外一侧创建一个对称点(斜率不变),能够经过一个简写 的命令来实现,这个命令是S(或s)。(这段话能够这样理解:S命令前面能够是一条C命令建立的三次贝赛尔曲线,这时候,S命令跟在C命令的后面,就能够 用比较简单的参数,生成一个与前面那个相对称的三次贝塞尔曲线。仔细看一下后面的图例,能够帮助理解。另外,S命令也能够跟在S命令后面。)
S x2 y2, x y (or s dx2 dy2, dx dy)
S命令能够用来建立与以前那些曲线同样的贝塞尔曲线,可是,若是S命令跟在一个C命令或者另外一个S命令的后面,它的第一个控制点,就会被假设成前一 个控制点的对称点。若是S命令单独使用,前面没有C命令或者另外一个S命令,那么它的两个控制点就会被假设为同一个点。下面是S命令的语法示例,如图所示, 左侧的控制点用红色标示,与它对称的控制点用蓝色标示。
<?xml version="1.0" standalone="no"?> <svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/> </svg>
另外一个贝塞尔曲线是二次贝塞尔曲线Q,它比三次贝塞尔曲线简单,只须要一个控制点,用来肯定起点和终点的曲线斜率。所以它须要两组参数,控制点和终点坐标。
Q x1 y1, x y (or q dx1 dy1, dx dy)
<?xml version="1.0" standalone="no"?> <svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg""> <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/> </svg>
就像三次贝塞尔曲线有一个S命令,二次贝塞尔曲线有一个差很少的T命令,能够经过更简短的参数,延长二次贝塞尔曲线。
T x y (or t dx dy)
和以前同样,快捷命令T会经过前一个控制点,推断出一个新的控制点。这意味着,在你的第一个控制点后面,能够只定义终点,就建立出一个至关复杂的曲 线。须要注意的是,T命令前面必须是一个Q命令,或者是另外一个T命令,才能达到这种效果。若是T单独使用,那么控制点就会被认为和终点是同一个点,因此画 出来的将是一条直线。
<?xml version="1.0" standalone="no"?> <svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/> </svg>
虽然三次贝塞尔曲线拥有更大的自由度,可是两种曲线能达到的效果老是差很少的。具体使用哪一种曲线,一般取决于需求,以及对曲线对称性的依赖程度。
弧形命令A是另外一个建立SVG曲线的命令。基本上,弧形能够视为圆形或椭圆形的一部分。假设,已知椭圆形的长轴半径和短轴半径,另外已知两个点(它 们的距离在圆的半径范围内),这时咱们会发现,有两个路径能够链接这两个点。每种状况均可以生成出四种弧形。因此,为了保证建立的弧形惟一,A命令须要用 到比较多的参数:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy
弧形命令A的前两个参数分别是x轴半径和y轴半径,它们的做用很明显,不用多作解释,若是你不是很清楚它们的做用,能够参考一下椭圆ellipse命令中的相同参数。弧形命令A的第三个参数表示弧形的旋转状况,下面的例子能够很好地解释它:
<?xml version="1.0" standalone="no"?> <svg width="320px" height="320px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 315 L 110 215 A 30 50 0 0 1 162.55 162.45 L 172.55 152.45 A 30 50 -45 0 1 215.1 109.9 L 315 10" stroke="black" fill="green" stroke-width="2" fill-opacity="0.5"/> </svg>
如图例所示,画布上有一条对角线,中间有两个椭圆弧被对角线切开(x radius = 30, y radius = 50)。第一个椭圆弧的x-axis-rotation(x轴旋转角度)是0,因此弧形所在的椭圆是正置的(没有倾斜)。在第二个椭圆弧中,x- axis-rotation设置为-45,因此这是一个旋转的椭圆,并以短轴为分割线,造成了两个对称的弧形。参看图示中的第二个椭圆形。
上面提到的四种不一样路径将由接下来的两个参数决定。如前所讲,还有两种可能的椭圆用来造成路径,它们给出的四种可能的路径中,有两种不一样的路径。这 里要讲的参数是large-arc-flag(角度大小) 和sweep-flag(弧线方向),large-arc-flag决定弧线是大于仍是小于180度,0表示小角度弧,1表示大角度弧。sweep- flag表示弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧。下面的例子展现了这四种状况。
<?xml version="1.0" standalone="no"?> <svg width="325px" height="325px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M80 80 A 45 45, 0, 0, 0, 125 125 L 125 80 Z" fill="green"/> <path d="M230 80 A 45 45, 0, 1, 0, 275 125 L 275 80 Z" fill="red"/> <path d="M80 230 A 45 45, 0, 0, 1, 125 275 L 125 230 Z" fill="purple"/> <path d="M230 230 A 45 45, 0, 1, 1, 275 275 L 275 230 Z" fill="blue"/> </svg>
你应该已经猜到了,最后两个参数是指定弧形的终点,弧形能够简单地建立圆形或椭圆形图标,好比你能够建立若干片弧形,组成一个饼图。
若是你是从Canvas过 渡到SVG,那么弧形会比较难以掌握,但它也是很是强大的。用路径来绘制完整的圆或者椭圆是比较困难的,由于圆上的任意点均可以是起点同时也是终点,无数 种方案能够选择,真正的路径没法定义。经过绘制连续的路径段落,也能够达到近似的效果,但使用真正的circle或者ellipse元素会更容易一些。