重学SVG

重学SVG

SVG

可缩放矢量图形(Scalable Vector Graphics,SVG)
它介于DOMCanvas之间,既提供了图形的绘制能力,又提供了元素的DOM交互能力。所以它很适合用来制作交互复杂的图形应用。比如地图,流程图等。

  • SVG可由文本编辑器编辑
  • SVG是XML格式
  • SVG高精度缩放不失真

和Canvas的比较

  • 首先最大的区别在于,SVG是矢量图形,而Canvas绘制的是位图。
  • 其次,当屏幕尺寸越大时,SVG的渲染速度差异不大,但是Canvas的渲染时长明显增加
  • 当绘制对象过多时,SVG的渲染时长指数增加,Canvas保持稳定增长
  • Canvas不支持DOM事件

SVG_Canvas.png

和DOM比较

首先,SVG是设计用于绘图和动画的,虽然CSS3也有类似的效果,但是他们的载体却截然不一样。SVG的子元素都是以坐标轴定位的,不存在回流这种布局问题,最多也就是重绘。但是DOM的动画就可能导致回流。

然后SVG可以绘制各种各样的图形,并且可以在图形编辑器中绘制并导出,DOM就不太行了。

开始

要开始一个SVG,需要定义一个根元素

<svg width="400" height="400"></svg>

widthheight定义了其画布大小,类似canvas

接着,你可以把svg理解为只有absolute布局的Body。所有的子svg元素都需要指定xy来进行定位,这里没有流式布局。

也就是说,svg元素带有一个坐标轴。
Canvas_default_grid.png

所有子元素(不包括孙)的坐标都以该坐标轴为参照。

视口

在定义了画布大小之后,如果没有定义视口,则画布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),宽高widthheight,圆角rxry

直线

<line x1="20" y1="100" x2="100" y2="20" />

起始坐标(x1, y1)和终点坐标(x2, y2)

椭圆

<ellipse cx="60" cy="60" rx="50" ry="25"/>

圆心坐标(cx, cy),长短轴半径rxry

复杂图形绘制

多边形

<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
画圆弧可以想象为截断传过两个点的椭圆,由于对称性,会有两个符合条件的椭圆,也就是有四段圆弧可供选择。
rxry为该椭圆的半径,LargeArcFlag表示截取大圆弧还是小圆弧。SweepFlag表示截取顺时针的圆弧还是逆时针的圆弧。
xy表示终点坐标。

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>

复用

使用defsuse来创建和使用一个可复用的图形或者效果。

渐变

<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中的animationstep定义。
可以在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。当宽高为绝对值时,会重复渲染该图案。

上一篇 斐波那切数列的三种实现方法
下一篇 JS事件循环