SVG 路径(path)

本文转自:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths

<path>元素是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。

另外,path只需要设定很少的点,就可以创建平滑流畅的线条(比如曲线)。虽然polyline元素也能实现类似的效果,但是必须设置大量的点 (点越密集,越接近连续,看起来越平滑流畅),并且这种做法不能够放大(放大后,点的离散更明显)。为了更好的理解path,你最好用path实际画一个 SVG图形,虽然用XML或文本编辑器来编辑path元素不是很容易,但可以帮助我们理解path是如何工作的,所以,你就忍了吧。

上一章提到过,path元素的形状是通过d属性定义的,d属性的值是一个“命令+参数”的序列,我们将学习这些命令,并且看到很多相关的示例。

每一个命令都用一个关键字母来表示,比如,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点。跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标。比如移动到 (10,10)这个点的命令,应该写成“M 10 10”。这一段字符结束后,解析器就会去读下一段命令。每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位(例如:从上一个点开始,向上移动10px,向左移动7px)。

d属性采用的是用户坐标系统,不需标明单位。在后面的教程中,我们会学到如何让变换path,以满足更多需求。

直线命令 Line commands

<path>元素有5个画直线的命令,如名字所示,直线命令就是在两个点之间画直线。首先是“Move to”命令,M,前面已经提到过,它有两个参数,分别是需要移动到的点的x轴和y轴的坐标。假设,你的画笔当前位于一个点,在使用M命令移动画笔后,只会 移动画笔,但不会在两点之间画线。因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。

M x y

or

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>

能够真正画出线的命令有3个(M命令是移动画笔位置,但是不画线),最常用的是“Line to”命令,LL有两个参数,分别是一个点的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在这方面的语法会更复杂一 些。

曲线命令 Curve commands

绘制平滑曲线的命令有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>

虽然三次贝塞尔曲线拥有更大的自由度,但是两种曲线能达到的效果总是差不多的。具体使用哪种曲线,通常取决于需求,以及对曲线对称性的依赖程度。

弧形Arcs

弧形命令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元素会更容易一些。

时间: 2024-10-10 19:59:54

SVG 路径(path)的相关文章

深度掌握SVG路径path的贝塞尔曲线指令

一.数字.公式.函数.变量,哦,NO! 又又一次说起贝塞尔曲线(英语:Bézier curve,维基百科详尽中文释义戳这里),我最近在尝试实现复杂的矢量图形动画,发现对贝塞尔曲线的理解馒头那么厚,是完全不能承受富有创意的创作的,至少得有我当年追我老婆的脸皮厚才行. 然而,瞅瞅维基百科上的释义,或者其他一些相关的技术文章,总是离不开各种公式,一大堆变量……例如下面维基截图缩略图: 完全是数学爱好者的菜啊!我想,要是让UI设计师们去学习这些东西,估计还不如一刀来个痛快的! 这就是爱好领域与能力掌握的

svg 路径path

<path> 标签用来定义路径. 下面的命令可用于路径数据: M = moveto(M X,Y) :将画笔移动到指定的坐标位置L = lineto(L X,Y) :画直线到指定的坐标位置H = horizontal lineto(H X):画水平线到指定的X坐标位置V = vertical lineto(V Y):画垂直线到指定的Y坐标位置C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线S = smooth curveto(S X2,Y2,ENDX,END

SVG路径path的贝塞尔曲线指令

深度好文分享: http://www.zhangxinxu.com/wordpress/2014/06/deep-understand-svg-path-bezier-curves-command/ 二次,三次贝塞尔曲线控制图代码生成器: http://dayu.pw/svgcontrol/

SVG路径

前面的话 本文将详细介绍SVG路径 path字符串 路径(path)是一个非常强大的绘图工具,可以用path元素绘制矩形(直角矩形或者圆角矩形).圆形.椭圆.折线形.多边形,以及一些其他的形状,例如贝塞尔曲线.2次曲线等曲线 SVG路径最常用的属性是d属性,即path字符串,用来定义path元素的路径形状 属性d的值是一个“命令+参数”的序列,每一个命令都用一个关键字母来表示.参数之间可以用空格或逗号隔开,有一种情况例外,就是下一个数值是负数 d 一个点集数列以及其它关于如何绘制路径的信息 <p

SVG 学习&lt;七&gt; SVG的路径——path

SVG的path可以理解外一支画笔,由一连串的命令控制画笔在SVG中绘制需要的形状. path通过属性 d 来编写画笔命令. 命令说明: 其中 大写命令坐标是绝对位置,小写命令坐标是相对位置. 直线命令: 例(大写命令): <path d="M10 10,L200 200,V50,H10,L10 10"/> 例(小写命令): <path d="m10 10,l200 200,v50,h10,l10 10"/> 直线命令解析: M/m:移动命令

segment-实现SVG路径描边绘制与动画的轻量库

今天来一起了解一个实现SVG路径描边绘制与动画的轻量级类库segment,我们从轻松上手.使用详解.资源和案例.源码解读等几个方面进行介绍. 1. 轻松上手 html方面添加segment,定义path. <script src="/dist/segment.min.js"></script> <svg> <path id="my-path" ...> </svg> JS方面利用path实例化一个segme

SVG路径动画解密

原文:SVG路径动画解密 原文链接:http://www.gbtags.com/gb/share/5581.htm SVG路径动画效果现在貌似越来越多网站都使用了,给我的感觉就像是一段时间的流行而已,刚一出来大家都感觉很炫酷,时间久了也就审美疲劳啦!如果还不知道什么是SVG路径动画的童鞋,快来看一个demo吧:http://tympanus.net/Development/SVGDrawingAnimation/ 课程库相关课程:?常用的三种生成SVG图形动画方式 怎么样?是不是很炫酷!另外这种

使用snapjs实现svg路径描边动画

一,snap.svg插件在近几天,突然接到一个需求,内容是要在网页上写一个路径的动画,还需要可以随意控制动画的速度,开始于结束,本来是一个图片可以解决的问题,结果就这样变难了呀,在网上查一会之后,突然就发现了svg,他有两个神奇属性stroke-dasharray(控制虚线和空白大小)和stroke-dashoffset(控制虚线偏移),通过改变stroke-dashoffset便可以轻松实现路径动画. 路径是这样滴  一开始没有注意后边路径上的阴影,我写到阴影时候才发现,svg的阴影竟然是用矩

WPF Data Binding之控件作为源(Source)与路径(Path)【一】

Binding 的源也就是数据的源头.Binding对源的要求并不苛刻------只要它是一个对象,并且通过属性(Property)公开自己的数据,它就能作为Binding 的源. 前面一个例子已经向大家证明,如果想让作为Binding源的对象具有自动通知Binding自己属性值已经已经变化的能力,那么就需要让类实现INotifyChanged接口并在属性的Set语句中激发PropertyChanged事件.在日常生活中,除了使用这种对象作为数据源之外,我们还有更多的选择,比如用一个控件做为另一