最近接触到SVG动画,这个技术在以往的网页制作中都很少用。之前的网页动效基本都是用CSS+JavaScript或者Canvas 和 WebGL实现的。Canvas 和 WebGL这两项图形技术结合 CSS3 可以说能完成绝大部分的动画和需求。但Canvas和 WebGL 毕竟是偏向底层的绘制引擎,某些场景使用起来还是过于繁琐的,不分场合一律使用锤子解决的行为不值得提倡。SVG在解决排版,图标,相关动画还是非常高效的,而且 SVG还是矢量图形,高清还原各种屏幕尺寸的设计简直就是神器。而在有些特定的场景下JavaScript被禁用,这时候要想实现动画效果的话就不得不使用SVG了。下面就记录一下SVG动画的原理和具体实现方式。
一 、概述
SVG 意为可缩放矢量图形(Scalable Vector Graphics),是基于 XML 的矢量图形描述语言,可以近似理解成 HTML,所以能和 JS 以及 CSS 进行交互。 特别是 CSS,我们可以使用 CSS3 来对 SVG 做动画处理。它允许你通过在2D平面中确定的一组点来绘制路径、曲线和形状。 此外你还可以通过在这些路径上添加动态属性(例如笔触,颜色,粗细,填充等)来生成动画。SVG简单的矢量图可以通过一些工具直接生成,要实现稍微复杂的动画效果则需要特定的SVG元素和标签来实现。
二 、SVG 常用元素
1.SVG 路径 - <path>
元素用于定义一个路径。
比如:定义一条路径,它开始于位置150 0,到达位置75 200,然后从那里开始到225 200,最后在150 0关闭路径。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M150 0 L75 200 L225 200 Z" />
</svg>
2.SVG 文本 - <text>
<text> 元素用于定义文本。比如:实现一段文本:I love SVG
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<text x="0" y="15" fill="red" transform="rotate(30 20,40)">
I love SVG
</text>
</svg>
3. SVG Stroke 属性
SVG提供了一个范围广泛stroke 属性。所有stroke属性,可应用于任何种类的线条,文字和元素就像一个圆的轮廓。
比如:画三条不同颜色的线条
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g fill="none">
<path stroke="red" d="M5 20 l215 0" />
<path stroke="blue" d="M5 40 l215 0" />
<path stroke="black" d="M5 60 l215 0" />
</g>
</svg>
4.SVG 模糊效果
<feGaussianBlur>元素是用于创建模糊效果。
比如:让一块布变模糊
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f1)" />
</svg>
5.SVG 阴影
<feOffset>元素是用于创建阴影效果。
比如:偏移一个矩形(带<feOffset>),然后混合偏移图像顶部(含<feBlend>)
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="f1" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
<feBlend in="SourceGraphic" in2="offOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" stroke="green" stroke-width="3"
fill="yellow" filter="url(#f1)" />
</svg>
6.SVG 渐变 - 线性
渐变是一种从一种颜色到另一种颜色的平滑过渡。另外,可以把多个颜色的过渡应用到同一个元素上。
比如:定义水平线性渐变从黄色到红色的椭圆形
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>
7. SVG 渐变- 放射性
<radialGradient>元素用于定义放射性渐变。
比如:定义一个放射性渐变从白色到蓝色椭圆
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>
三、SVG动画的实现方式
SVG动画的实现方式有三种:SMIL 驱动、JavaScript 驱动、CSS 驱动。因为我们特定的使用场景是禁用JavaScript的,所以采取的方式一般是SMIL 驱动+ CSS 驱动。以下是三种方式的比较:
| 技术 | 描述 | 备注 |
| SMIL | 很强大且纯粹的标签化动画 | 虽然 Chrome 45以后弃用了SMIL,但是依然支持,各大浏览器的支持度都挺好的 |
| CSS | CSS 还只能实现简单的动画 | offset-path 的兼容性很差。css 动画不适合做交互性很强的动画 |
| JavaScript | 复杂动画就要用到 JS 了,包括世面上的一些 SVG 动画库,也都是 JS 去实现的 | 在有些禁用js的场景下无法使用 |