SVG path
在网页上画一图形,比如星星或波浪线,开始是想着图形软件画一个的,后来发现SVG这绘图程序的语言,感觉甚是可以,就发了些时间学了一下,在此做一简单分享和记录。
菜鸟上是这么介绍的(SVG 是使用 XML 来描述二维图形和绘图程序的语言。SVG 指可伸缩矢量图形 (Scalable Vector Graphics),SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失,SVG 是万维网联盟的标准。。。。)
而且SVG 文件可通过<embed>、<object> 或者 <iframe>标签嵌入 HTML 文档。也可以直接嵌入到HTML页面中,或您可以直接链接到SVG文件。反正使用起来还是挺方便的 ,只要浏览器支持,推荐浏览器能支持HTML5的使用。
SVG确是很强大,能够绘制各种基本图形(矩形、圆、椭圆、多边形、曲线、路径、文本等),还有各种滤镜、模糊效果、阴影、渐变等特效。然后其中的路径path它不仅能创建其他基本形状,还能创建更多复杂形状(抛物线、波浪线.....甚至all)。反正path又是SVG里强大的一个,所以这里单独来讨论path。
path中存在很多命令来定义路径形式和路径数据。可大致分为直线命令和曲线命令
直线命令
M = moveto
字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点。跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标。比如移动到(10,10)这个点的命令,应该写成“M 10 10”。这一段字符结束后,解析器就会去读下一段命令。因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。比如:
<svg width="200px" height="200px" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10"/> </svg>
这样是看不到任何图像的,因为这样只是把画笔移动到了x-10px,y-10px处。需要画出东西得在后面跟上其他画图命令如下面介绍到的命令。
注:每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位,(例如:从上一个点开始,向上移动10px,向左移动7px)path元素的形状是通过属性d定义的,因为属性d采用的是用户坐标系统,所以不需标明单位。
L = lineto
字母“L”表示的是“line to”命令,L需要两个参数,分别是一个点的x轴和y轴坐标,L命令将会在当前位置和新位置(L前面画笔所在的点)之间画一条线段。这里就一起把“H”和“V”两个命令一起介绍了,
- H = horizontal lineto ——绘制平行线。
- V = vertical lineto ——绘制垂直线。
这两个命令都只带一个参数,标明在x轴或y轴移动到的位置,因为它们都只在坐标轴的一个方向上移动。比如,绘制平行线只需要确定x轴(H x),绘制垂直线只需确定y轴 ( V x )。
现在来整理以上命令绘制一个简单的矩形(当然SVG中有专门的 矩形命令<rect/>)。
<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10 H 100 V 100 H 10 L 10 10" stroke="black"/> </svg>
上述路径是:画笔移动到(10,10)点,由此开始,向右移动90像素构成一条水平线,然后向下移动90像素,然后向左移动90像素,然后再向上移动100再回到起点。
Z = closepath
“Z”命令为路径闭合命令,Z命令会从当前点画一条直线到路径的起点,尽管我们不总是需要闭合路径,但是它还是经常被放到路径的最后。另外,Z命令不用区分大小写。
然后实际上上面的例子我们可以优化为
<path d="M10 10 H 100 V 100 H 10 Z" stroke="black" fill="transparent"/>
注:stroke:路径颜色,fill:闭合路径的填充颜色,stroke-width:路径宽度
曲线命令
绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,最后一个用来绘制弧形或者说是圆的一部分(主要介绍C、S,A圆弧曲线这里将不予讨论)。
- C = curveto
- Q = quadratic Bézier curve
- A = elliptical Arc
C 和 Q 是用来绘制贝塞尔曲线的,“贝塞尔曲线”是什么?这东西老难解释了,在这实际上也用不着深入研究,如果有兴趣可以阅读这份Wikipedia的文档。贝塞尔曲线的类型有很多(线性贝塞尔曲线、二次方贝塞尔曲线、三次方贝塞尔曲线、四次方贝塞尔曲线、五次方贝塞尔曲线、……。),但是在path元素里,只存在两种贝塞尔曲线:三次贝塞尔曲线C,和二次贝塞尔曲线Q。
三次贝塞尔曲线C:
C x1 y1, x2 y2, x y
<path d="M10 10 C 30 50, 100 60, 200 10" stroke="black" fill="transparent"/>
x1 y1, x2 y2 是两个控制点,x y 为曲线终点,这里盗一下图:
是不是很熟悉,在ps中绘制曲线的钢笔工具绘制的实际上就是“贝塞尔曲线”。
是不是多条三次贝塞尔曲线组合在一起可以得到一条很长的变化莫测的(^-<)平滑曲线,确实。但那是不是描点很麻烦,确实,所以 出现了S ( smooth curveto)命令,S命令可以用来创建与之前那些曲线一样的贝塞尔曲线,
但是,如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。如果S命令单独使用,前面没有C命令或者另一个S命令,
那么它的两个控制点就会被假设为同一个点,变成了二次贝塞尔曲线。
(MDN 贝塞尔曲线示意图)。
<path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"> ,M10 80 确定了画笔起点,C 后跟了两个控制点坐标,这时已经完成了一条三次贝塞尔曲线了,然后当我们需要再次绘制一条连接第一条曲线的
贝塞尔曲线时,跟上S命令后只需给出第二条三次贝塞尔曲线的第二个控制点的坐标即可(S指令会自动补出第一个控制点与第二个控制点对称 [蓝色部分]),于是就可以绘制出一条完美的平滑曲线了。
C指令有三个坐标参数,而S指令自动对称一个控制点,因此,跟在C指令之后的S指令,只需要2个参数,如下:
S x2 y2, x y
另一种可用的贝塞尔曲线是二次贝塞尔曲线Q,它比三次贝塞尔曲线简单,只需要确定一个控制点和一个终点即可(当然还有起点)。
<path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
如下图:
A和C分别是起点和终点,B是控制点,其指令和参数为:
Q x1 y1, x y
同样,Q二次贝塞尔曲线也存在一简化连续绘制平滑曲线的命令,他就是T (smooth quadratic Bézier curveto)。
T会通过前一个控制点,推断出一个新的控制点。这意味着,在你的第一个控制点后面,可以只定义终点,就创建出一个相当复杂的曲线。需要注意的是,T命令前面必须是一个Q命令,
或者是另一个T命令,才能达到这种效果。如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线。继续上MDN示意图:
下面蓝色的控制点就是T命令自动补上的。
<path d="M10 80 Q 185 10, 360 80 T 720 80" stroke="black" fill="transparent"/> <path d="M10 80 Q 95 10,185 80 T 360 80" stroke="black" fill="transparent"/> <path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/>
(效果图)
虽然二次贝塞尔曲线绘制比较三次贝塞尔曲线简单,但三次贝塞尔曲线拥有更大的自由度,具体使用哪种曲线,通常取决于需求,以及对曲线对称性的依赖程度。
最后附上一张绘制前的草图
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"> <path d="M10 80 Q 210 0 ,400 80 T 800 80 T 1200 80 T 1600 80" stroke="black" fill="transparent"> </svg>
画笔由原点向下移动了80px向左移动了10px,然后绘制了第一条二次贝塞尔曲线紧接着使用T指令绘制了第二条第三条第四条……,一条很长的波浪线就横空出世了。
SVG绘制的为矢量图,我感到最大的好处是可以动态的改变图形的形状和颜色,用来作动画真的太赞了(像我这种绘画艺术细菌为零的程序猿)。
参考文章: