http://www.w3.org/TR/SVG/paths.html#PathData
http://www.w3.org/TR/svg-paths/
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute/d
Attribute definitions:
1
如上一章所说,<path>
元素是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。
另外,path只需要设定很少的点,就可以创建平滑流畅的线条(比如曲线)。虽然polyline
元素也能实现类似的效果,但是必须设置大量的点(点越密集,越接近连续,看起来越平滑流畅),并且这种做法不能够放大(放大后,点的离散更明显)。所以在绘制SVG时,对路径的良好理解很重要。虽然用XML或文本编辑器来编辑path元素不是很容易,但可以帮助我们理解path是如何工作的,所以,你就忍了吧。
上一章提到过,path元素的形状是通过属性
定义的,属性d
d
的值是一个“命令+参数”的序列,我们将讲解这些可用的命令,并且展示一些示例。
每一个命令都用一个关键字母来表示,比如,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点。跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标。比如移动到(10,10)这个点的命令,应该写成“M 10 10”。这一段字符结束后,解析器就会去读下一段命令。每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位(例如:从上一个点开始,向上移动10px,向左移动7px)。
因为属性d
采用的是用户坐标系统,所以不需标明单位。在后面的教程中,我们会学到如何让变换路径,以满足更多需求。
<path>
元素里有5个画直线的命令,顾名思义,直线命令就是在两个点之间画直线。首先是“Move to”命令,M,前面已经提到过,它需要两个参数,分别是需要移动到的点的x轴和y轴的坐标。假设,你的画笔当前位于一个点,在使用M命令移动画笔后,只会移动画笔,但不会在两点之间画线。因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。
M x y
或
m dx dy
这有一个比较好的例子,不过我们没画任何东西,只是将画笔移动到路径的起点,所以我们不会看到任何图案。但是,我把我们移动到的点标注出来了,所以在下面的例子里会看到(10,10)坐标上有一个点。注意,如果只画path,这里什么都不会显示。(这段不太好理解,说明一下:为了更好地展示路径,下面的所有例子里,在用path绘制路径的同时,也会用circle标注路径上的点。)
<?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>
能够真正画出线的命令有三个(M命令是移动画笔位置,但是不画线),最常用的是“Line to”命令,L
,L
需要两个参数,分别是一个点的x轴和y轴坐标,L命令将会在当前位置和新位置(L前面画笔所在的点)之间画一条线段。
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在这方面的语法会更复杂一些。
绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,另外一个用来绘制弧形或者说是圆的一部分。如果你在Inkscape、Illustrator或者Photoshop中用过路径工具,可能对贝塞尔曲线有一定程度的了解。欲了解贝塞尔曲线的完整数学讲解,请阅读这份Wikipedia的文档。在这里不用讲得太多。贝塞尔曲线的类型有很多,但是在path元素里,只存在两种贝塞尔曲线:三次贝塞尔曲线C,和二次贝塞尔曲线Q。
我们从稍微复杂一点的三次贝塞尔曲线C入手,三次贝塞尔曲线需要定义一个点和两个控制点,所以用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 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,所以这是一个旋转了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元素会更容易一些。
1
该属性定义了一个路径。
类别 | 路径定义属性 |
---|---|
值 | |
可变性 | Yes |
规范文档 | SVG 1.1 (2nd Edition) |
属性d
实际上是一个字符串,包含了一系列路径描述。这些路径由下面这些指令组成:
这些组合在一个字符串中。这些不同的命令是大小写敏感的;一个大写的命令指明它的参数是绝对位置,而小写的命令指明相对于当前位置的点。可以指定一个负数值作为命令的参数:负角度将是逆时针的,绝对x和y位置将视为负坐标。负相对x值将会往左移,而负相对y值将会向上移。
Moveto
指令可以被想象成拎起绘图笔,落脚到另一处。在上一个点和这个指定点之间没有线段绘制。用一个Moveto命令开始一个路径是好的作法,因为如果没有一个初始化的Moveto,执行命令时开始点会是上一个操作发生过的地方,这样可能造成不确定的行为。
句法:
M x,y
在这里x和y是绝对坐标,分别代表水平坐标和垂直坐标。m dx,dy
在这里dx和dy是相对于当前点的距离,分别是向右和向下的距离。示例:
<path d="M50,100..." />
<path d="m50,100..." />
和Moveto
指令不同,Lineto
指令将绘制一条直线段。这个直线段从当前位置移到指定位置。原生的Lineto
命令的句法是”L x, y“或者”l dx, dy“,在这里x和y是绝对坐标,而dx和dy分别是向右和向下的距离。还有字母H和V,分别指定水平和垂直移动。它们的句法与L相同,它的小写版本是相对距离,大写版本是绝对位置。
Curvto命令指定了一个贝塞尔曲线。有两种类型的贝塞尔曲线:立方曲线和二次方曲线。二次方贝塞尔曲线是一种特殊的立方贝塞尔曲线,在这里,控制点的两端是相同的。二次方贝塞尔曲线的句法是”Q cx, cy x, y“或”q dcx, dcy dx, dy“。cx和cy都是控制点的绝对坐标,而dcx和dcy分别是控制点在x和y方向上的距离。
立方贝赛尔曲线遵守二次方贝赛尔曲线同样的概念,但是它需要考虑两个控制点。立方贝塞尔曲线的句法是:”C c1x,c1y c2x,c2y x,y“或者”c dc1x,dc1y dc2x,dc2y dx,dy“,在这里,c1x、c1y和c2x、c2y是分别是初始点和结束点的控制点的绝对坐标。dc1x、dc1y和dc2x、dc2y都是相对于初始点,而不是相对于结束点的。dx和dy分别是向右和向下的距离。
为了连缀平滑的贝塞尔曲线,还可以使用T和S命令。它们的语法比别的Curveto命令简单,因为它假定第一个控制点是从前一个控制点关于前一个点的反射,或者说如果没有前一个控制点的话它实际上就是前一个点。T的句法是”T x,y“或者”t dx,dy“,分别对应于绝对坐标和相对距离,用来创建二次方贝塞尔曲线。S用来创建立方贝塞尔曲线,语法是”S cx,cy x,y“或者”s dcx,dcy dx,dy“,在这里(d)cx指定第二个控制点。
最后,所有的贝塞尔曲线命令可以制作出一个多边贝塞尔图形,先初始化命令,然后多次指定所有的参数,就可以制作出一个多边贝赛尔图形。因此,下面的两个命令可以创建完全相同的路径:
<path d="c 50,0 50,100 100,100 50,0 50,-100 100,-100" />
<path d="c 50,0 50,100 100,100 c 50,0 50,-100 100,-100" />
有时候描述一个椭圆弧曲线路径要比描述一个贝塞尔曲线路径更简单。说到底,path元素支持Arcto命令。圆弧的中心由别的变量计算出。一个arcto的声明相对而言有点复Visual Studio:”A rx,ry xAxisRotate LargeArcFlag,SweepFlag x,y“。解构它,rx和ry分别是x和y方向的半径,而LargeArcFlag的值要到是0要么是1,用来确定是要画小弧(0)还是画大弧(1)。SweepFlag也要么是0要么是1,用来确定弧是顺时针方向(1)还是逆时针方向(0)。x和y是目的地的坐标。虽然xAxisRotate支持改变x轴相对于当前引用框架的方向,但是在Gecko 7中,这个参数看起来没什么效果。
ClosePath命令将在当前路径从,从当前点到第一个点简单画一条直线。它是最简单的命令,而且不带有任何参数。它沿着到开始点的最短的线性路径,如果别的路径落在这路上,将可能路径相交。句法是”Z“或”z“,两种写法作用都一样。
以下元素可以使用d
属性:
同样的规则可以应用到<animate>
动画路径上。
原点(坐标系0,0点)经常是上下文的左上角。然而<glyph>
元素的原点在它的字母框的左下角。
在任何两个数字之间允许加一个逗号,但是在别的地方不允许加逗号。
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#F7931E" d="M37,17v15H14V17H37z M50,0H0v50h50V0z"/>
</svg>
为了演示d="M37,17v15H14V17H37z M50,0H0v50h50V0z"的实际意义,我们来讨论这个字符串的每一小段。
d=" M37,17 || v15 || H14 || V17 || H37 ||z // M50,0 || H0 || v50 || h50 || V0 || z"
d=
M37,17
17开始svg位置,在y轴的17像素处。
H14
V17
z
,
M50,0
H0
v50
h50
V0
z
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
http://www.w3.org/TR/2dcontext/
http://www.w3.org/TR/2dcontext2/
status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
Beware. This specification is no longer in active maintenance and the HTML Working Group does not intend to maintain it further.
If you wish to make comments regarding this document in a manner that is tracked by the W3C, please submit them via using our public bug database. If you cannot do this then you can also e-mail feedback to public-html-comments@w3.org (subscribe, archives), and arrangements will be made to transpose the comments to our public bug database. All feedback is welcome.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
原文:http://www.cnblogs.com/xgqfrms/p/4962763.html