最近看到一篇颇有趣的关于动画的文章,想拿来作个练习,里面用到了SVG,因此花了一些时间了解了一下SVG,在这里作一个记录,方便自查git
全部文章均同步到个人博客github
.svg
文件直接用浏览器打开chrome
用<iframe>
嵌入SVG浏览器
<iframe src="xx.svg" width="200" height="200" ></iframe>
用<img>
嵌入SVG网络
<img src="xx.svg" width="300" />
用CSS背景图的方式嵌入SVGapp
div { background: url('xx.svg') no-repeat center; background-size : 200px 200px; }
直接使用<svg>
元素svg
<svg width="600px" height="300px" viewBox="0 0 250 250"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/> <rect x="150" y="50" width="200" height="100" style="stroke: blue; fill: none;"/> <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: rgba(0,0,0,.5);"/> </svg> </svg>
后面还有两种embed和object方式,不建议使用,就不作介绍了。工具
经常使用<img>
和<svg>
,作背景图时用background-image
引入动画
.svg
文件常见写法:url
<?xml version="1.0"?> //XML声明 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="300"> <!-- SVG代码 --> </svg> //xmlns="http://www.w3.org/2000/svg"是声明空间
<svg>
<svg width="600px" height="300px" viewBox="0 0 250 250"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/> <rect x="150" y="50" width="200" height="100" style="stroke: blue; fill: none;"/> <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: rgba(0,0,0,.5);"/> </svg> </svg>
注意不用再写XML声明了。
<rect>
<circle>
<ellipse>
<line>
<polyline>
<polygon>
<path>
后面会重点介绍document.createElementNS(ns, tagName)
, ns是svg的命名空间element.appendChild(childElement)
element.setAttrbute(name, value)
,element.getAttribute(name)
好比:
var SVG_NS = 'http://www.w3.org/2000/svg'; var svg = document.createElementNS(SVG_NS, 'svg'); svg.setAttribute('width', '100%'); svg.setAttribute('height', '100%'); document.getElementById('svg-wrap').appendChild(svg);
重点来了,SVG的坐标系统
首先介绍一下SVG两个很重要的概念:viewport,viewBox
viewport,也能够叫作视窗,表示SVG可见区域的大小,超出这个区域的图形将不被显示出来,至关于将要做画的画板大小,在<svg>
中经过width
和height
来控制SVG的viewport的大小,注:若不加单位,则默认为px
<svg width="400" height="200" style="border:1px solid #7798CB"> <rect x="30" y="10" width="30" height="15" fill="#5CC26F" /> </svg>
效果以下,在svg可视区范围内,也就是viewport里的坐标为(30,10)的地方放了一个绿色矩形:
viewBox, 也能够叫视野,这个矩形区域定义了咱们要如何去观看svg在viewport上渲染出来的世界,借用张鑫旭大神的一个很好的比喻:“SVG就像是咱们的显示器屏幕,viewBox就是截屏工具选中的那个框框,最终的呈现就是把框框中的截屏内容再次在显示器中全屏显示”。这个在地图里应用很普遍,相似百度地图,谷歌地图,滑动滚轮就可让地图放大缩小的效果。
说了这么多,仍是动手写几个例子来体会一下,其中viewBox="x(左上角横坐标), y(左上角纵坐标), width, height"
<svg width="400" height="200" viewBox="0,0,400,200" style="border:1px solid #7798CB"> <rect x="30" y="10" width="30" height="15" fill="#5CC26F" /> </svg>
效果以下:
由于viewBox的宽高和svg的同样,至关于我透过跟svg同样大的窗户去看svg的世界,因此效果没有任何变化
修改一下viewBox的宽高
<svg width="400" height="200" viewBox="0,0,40,20" style="border:1px solid #7798CB"> <rect x="30" y="10" width="30" height="15" fill="#5CC26F" /> </svg>
这时,咱们看到svg里面的小矩形跑到了svg边框的右下角,同时还被放大到300*150,超出svg的部分不显示,有木有感觉到viewBox的巨大威力~~
这里为啥小矩形会被“挪到”右下角呢,这是由于viewBox的大小是40*20,并且从坐标(0,0)处开始,而rect的坐标是(30,10),那么我用viewBox去圈viewport的时候,rect就会出如今viewBox的右下方。专门作了一张图,帮助理解
上图比较形象的解释了小矩形的变化,接着将viewBox在viewport里全屏展现,这时rect的宽高会10倍放大,由于viewBox和viewport的width比例和height比例都是1/10,同时viewBox的宽高比和viewport的宽高比一致,都是2/1,那么rect的宽高都会放大10倍。
这是一种比较特殊的状况,固然也有两个比例不同的,这时就会使得图形变形扭曲(由于宽高不能等比例缩放),那么属性preserveAspectRatio
就须要用来强制统一缩放比来保持图形的宽高比。
preserveAspectRatio
是svg的一个属性,做用对象是viewBox,值为两个用空格分割的值组合而成。
做用:用来声明viewBox在视窗viewport中如何定位
preserveAspectRatio="xMidYMid meet"
第一个值,表示viewBox如何与viewport对齐:
x,y能够自由组合
第二个值的含义:
这个参数用来声明是否强制统一缩放,也就是如何来维持宽高比,若是是,那么该方法定义的规则会在viewBox的宽高比不等于viewport宽高比的时候生效。这里我刚看的时候感受理解上不是很容易,下面就列出我对这个知识点的理解方式,若是有错欢迎你们一块儿探讨。
动手写一个例子,帮助理解
<svg width="400" height="200" viewBox="0,0,40,40" preserveAspectRatio="xMidYMid meet" style="border:1px solid #7798CB"> <rect x="0" y="0" width="30" height="15" fill="#5CC26F" /> </svg>
效果:
从图中看到rect被放大到150*75
,怎么计算的呢?
viewBox如今是40*4
0,宽高比为1,而viewport是400*200
宽高比为2,两者如今不相等,viewport与viewBox的宽度比为:wr=400/40=10/1
,高度比为:hr=200/40=5/1
,因为指定的是meet,那么就要达到viewport包含viewBox的效果,同时保持viewBox的宽高比,这时viewBox该怎么同时知足这两个条件呢?
viewBox仍是很聪明的,它会按wr
和hr
中较小的那个值来进行宽高等比例缩放,这样就既能保持宽高比,还能被viewport包含啦~上例中得viewBox及里面的矩形rect的宽高就会都按5倍放大。
slice 保持viewbox的宽高比,使viewBox包含viewport
<svg width="400" height="200" viewBox="0,0,40,40" preserveAspectRatio="xMidYMid slice" style="border:1px solid #7798CB"> <rect x="0" y="0" width="30" height="15" fill="#5CC26F" /> </svg>
效果:
如今是slice,那么就须要达到viewBox包含viewport的效果,这时候聪明的viewBox就会选择wr
和hr
中值较大的那个进行放大(这里是由于viewBox比viewport小,因此须要放大来包含viewport,若是viewBox比viewport大,那么就须要缩小了,依旧乘以比例较大的那个值),也就是放大10倍,此时rect变为300*150,超出viewport的部分不显示,有剪切的效果。
<g></g>
来建立分组<g>
中建立的属性,子元素是能够继承的<g>
中能够用transform
来定义坐标变换,坐标变换会在后面作详细解释<g>
能够嵌套使用<svg> <g stroke="blue" fill="none" transform="translate(0, 50)"> <rect x="0" y="0" width="30" height="15" /> <circle cx="65" cy="75" r="10" /> </g> </svg>
这么一来就能够经过一个g,来控制包含在里面的全部图形的位置,颜色等属性。控制位移,那么就须要了解svg里的坐标系统了~且听下面的分析介绍~~很重要的概念
svg中的坐标系是这样的:
水平向右是x轴的正方向,竖直向下是y轴的正方向,角度的正方向为顺时针方向
四个比较重要的坐标系:用户坐标系,自身坐标系,前驱坐标系,参考坐标系
svg的坐标系,最原始的坐标系,其余几个坐标系都是从用户坐标系展开的。
viewBox就是定义了在用户坐标系的哪一个位置上看svg,以下图所示
自身坐标系是图形自身,或者分组的坐标系
好比
<svg> <rect x="0" y="0" width="30" height="15" fill="#5CC26F" /> </svg>
这个矩形自身有一个坐标系,rect里的x,y,width,height等属性都是根据其自身坐标系来定义的。
图中绿色的坐标系就是rect的自身坐标系
前驱坐标系就是父容器的坐标系,上图中,rect的前驱坐标系就是用户坐标系。
坐标变换实际上就是前驱坐标系通过一系列变换以后获得自身坐标系的过程。
<svg> <rect x="0" y="0" width="30" height="15" transform="translate(50,50)" fill="#5CC26F" /> </svg>
通过transform进行水平和竖直方向的50px的坐标偏移以后,rect的自身坐标系就跑到了上图中绿色坐标系的位置。若rect的属性x,y分别有值,好比x="10",y="10",则是相对于自身坐标系而言的。
选取一个坐标系做为参考坐标系,以此来描述图形的位置
<svg> <rect x="0" y="0" width="30" height="15" transform="translate(50,50)" fill="#5CC26F" /> </svg>
仍是这个例子,若是咱们把用户坐标系做为参考坐标系,那么在参考坐标系下,矩形rect的位置就是(50,50)。
svg中的坐标变换指的是将一个坐标系变换到另外一个坐标系的过程描述。
坐标变换中起到很大做用的一个属性,就是上面用到过的transform
transform就是定义了前驱坐标系到自身坐标系的一个线性变换
语法:
translate(<x>,<y>)
x表明x轴上的移动的值,y表明y轴上的移动的值。rotate(<deg>)
按角度deg进行旋转,自身坐标系相对于其前驱坐标系进行旋转scale(<sx>,<sy>)
sx表明沿x轴的缩放值,用来水平延长或者拉伸元素;sy表明沿y轴缩放值,用来垂直延长或者缩放元素。matrix(<a> <b> <c> <d> <e> <f>)
经过一个有6个值的变换矩阵声明一个变换。matrix(a,b,c,d,e,f)等同于添加变换matrix[a b c d e f]。较少使用。注意:若是有连续变换,那么每次的变换都是基于前一个变换后获得的自身坐标系的基础上进行变换。
路径path表现的是一个图形的外边沿,能够被填充,能够做为笔画,能够做为裁剪路径,或者任意前面三种的组合。path实际上就是用指令来控制画笔,将画笔放到某一个点上,而后拖动画笔,画出直线或曲线。
path中的属性d用来指定路径位置和形状,指令以下:
注意:命令区分大小写,大写表示坐标参数为绝对位置,小写为相对位置(相对于当前画笔的相对位置);最后的参数表示最后要到达的位置;上个命令结束的位置就是下一个命令开始的位置;命令能够重复参数表示重复执行同一条命令。
属性能够连续使用,举个例子:
<svg> <path d="M100 100 L150 300 L200 300 Z" /> </svg>
首先将画笔放到(100,100)处,而后移动画笔到(150,300)画出直线,而后又画直线到(200,300),最后在点(100,100)处关闭路径,造成闭合图形。
说一下弧线参数含义
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
<svg width="100%" height="1000px"> <path d="M 100 100 h 100 l -100 100 v -100 M 200 100 A 100 100 0 0 1 100 200" fill="#fff" stroke="red"/> </svg>
关于贝塞尔曲线,能够参考这里的demo加深理解,里面的起点和终点之间的点,就是贝塞尔曲线的控制点。