重学SVG
SVG
可缩放矢量图形(Scalable Vector Graphics,SVG)
它介于DOM
和Canvas
之间,既提供了图形的绘制能力,又提供了元素的DOM交互能力。所以它很适合用来制作交互复杂的图形应用。比如地图,流程图等。
- SVG可由文本编辑器编辑
- SVG是XML格式
- SVG高精度缩放不失真
和Canvas的比较
- 首先最大的区别在于,
SVG
是矢量图形,而Canvas
绘制的是位图。 - 其次,当屏幕尺寸越大时,
SVG
的渲染速度差异不大,但是Canvas
的渲染时长明显增加 - 当绘制对象过多时,
SVG
的渲染时长指数增加,Canvas
保持稳定增长 Canvas
不支持DOM事件
和DOM比较
首先,SVG
是设计用于绘图和动画的,虽然CSS3
也有类似的效果,但是他们的载体却截然不一样。SVG
的子元素都是以坐标轴定位的,不存在回流这种布局问题,最多也就是重绘。但是DOM
的动画就可能导致回流。
然后SVG
可以绘制各种各样的图形,并且可以在图形编辑器中绘制并导出,DOM
就不太行了。
开始
要开始一个SVG,需要定义一个根元素
<svg width="400" height="400"></svg>
width
和height
定义了其画布大小,类似canvas
。
接着,你可以把svg
理解为只有absolute
布局的Body
。所有的子svg
元素都需要指定x
和y
来进行定位,这里没有流式布局。
也就是说,svg
元素带有一个坐标轴。
所有子元素(不包括孙)的坐标都以该坐标轴为参照。
视口
在定义了画布大小之后,如果没有定义视口,则画布1:1全部显示。
<svg width="400" height="400" viewBox="0 0 100 100">
</svg>
但是在定义视口后,画布就被截取了,只会显示视口所展示的那部分,并且图像会被占满整个svg
。其属性的意思为:从(0,0)点开始,100宽*100高的区域。这样定义的视口,图像会被放大4倍。
所以我们在做缩放,拖拽视图时,只需要操作viewBox
就可以了。
基本图形绘制
圆形
<circle cx="60" cy="60" r="50"/>
圆心坐标(cx, cy)
,和半径r
矩形
<rect x="10" y="10" width="100" height="100" rx="2" ry="2" />
左上顶点的坐标(x, y)
,宽高width
和height
,圆角rx
和ry
直线
<line x1="20" y1="100" x2="100" y2="20" />
起始坐标(x1, y1)
和终点坐标(x2, y2)
椭圆
<ellipse cx="60" cy="60" rx="50" ry="25"/>
圆心坐标(cx, cy)
,长短轴半径rx
和ry
复杂图形绘制
多边形
<polygon points="0,100 50,25 50,75 100,0" />
通过几个点,最后首尾连接形成一个多边形。poly
是多的意思,gon
是角度的意思。
每个点的坐标由,
分割,多个点之间用空格分割。
折线
<polyline points="100,100 150,25 150,75 200,0" fill="none" stroke="black" />
和多边形类似,只是没有最后的首尾相连。
路径
最通用的绘制方法,可以用路径绘制任何以上图形。
<path d="M 100 100 L 300 100 L 200 300 z" />
d
为路径的描述。
其中的大写字母描述了绘制的方法,有以下几种:
Moveto
移动到,中间不绘制
M x, y
移动到绝对坐标(x, y)
m dx, dy
移动到相对于当前点坐标,横向移动dx
,竖向移动dy
Lineto
L x, y
画直线到坐标(x, y)
,同样有相对坐标版本。
并且有垂直移动V
和水平移动H
Curveto
贝塞尔曲线
Arcto
画圆弧到
A rx,ry xAxisRotate LargeArcFlag,SweepFlag x,y
画圆弧可以想象为截断传过两个点的椭圆,由于对称性,会有两个符合条件的椭圆,也就是有四段圆弧可供选择。
rx
和ry
为该椭圆的半径,LargeArcFlag
表示截取大圆弧还是小圆弧。SweepFlag
表示截取顺时针的圆弧还是逆时针的圆弧。
x
和y
表示终点坐标。
ClosePath
z
首尾相连
描边与填充
描边
描边可用于所有形状以及文本元素上。
基本用法是:
<path d="M 100 100 L 300 100" stroke="black" stroke-width="2"/>
stroke
属性表示描边的颜色。stroke-width
表示描边的宽度。
以上是其常用属性,描边还有其他属性:
stroke-opacity
描边的透明度stroke-dasharray="5, 10"
用于绘制虚线,5/10表示线段和空隙的长度。stroke-linecap
控制描边两端如何结束stroke-linejoin
控制描边转角的形状
填充
填充用于填充一个形状内部空间,值可以是颜色,或者链接
<circle cx="300" cy="20" r="20" fill="green"></circle>
<rect width="200" height="60" x="0" y="0" fill="url(#Gradient01)"></rect>
复用
使用defs
和use
来创建和使用一个可复用的图形或者效果。
渐变
<defs>
<linearGradient id="Gradient01" x1="0" y1="0" x2="0" y2="1">
<stop offset="20%" stop-color="#39F" stop-opacity="0.5"/>
<stop offset="90%" stop-color="#F3F" />
</linearGradient>
</defs>
<rect width="200" height="60" x="0" y="0" fill="url(#Gradient01)"></rect>
stop
用于定义渐变的阶段,类似于css
中的animation
的step
定义。
可以在fill
或者stroke
中使用url(#id)
来使用定义好的渐变。
渐变的方向则是由两个坐标(x1, y1)
,(x2, y2)
形成的矢量定义的。
模式
模式一般用于填充图案的定义。有点像定义PS里面的笔刷(→m→)
<defs>
<pattern id="GridDot" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse">
<circle cx="0" cy="0" r="2" fill="green"></circle>
</pattern>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#GridDot)"></rect>
patternUnits="userSpaceOnUse"
类似于background
中的repeat
。当宽高为绝对值时,会重复渲染该图案。