SVG动画基础及实现

958 阅读3分钟

最近接触到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,但是依然支持,各大浏览器的支持度都挺好的
CSSCSS 还只能实现简单的动画offset-path 的兼容性很差。css 动画不适合做交互性很强的动画
JavaScript复杂动画就要用到 JS 了,包括世面上的一些 SVG 动画库,也都是 JS 去实现的在有些禁用js的场景下无法使用