SVG 动画

2,154 阅读3分钟
—— 代码和艺术相交,诞生了 SVG 动画

SVG简介

SVG(可缩放矢量图),在近些年 SVG 的使用频率越来越高,但是 SVG 发明以来沉寂了很久,由于浏览器厂商对 SVG 的支持不够强大,所以在 Web 中使用的机会并不多。不过 SVG 的兼容性、可适配性使得可使用 SVG 的场景越来越多。

SVG 是很适合做动画的,因为他是由数字组成,本质上是利用几何图形进行绘制的。在 Web 上,数字容易被操作,也非常直观。

SVG 具有的优点:
• 数据可视化:真实的数据直观的表达了人们想要的想法,并且易于复杂思想的交流和展现。
• 响应式:SVG 是矢量图,具有独特的可伸缩性,能很好的适应各种屏幕。
• 性能表现:在 Web 应用或者页面中正确使用 SVG,可以减少页面加载的资源,特别是在响应式 Web 应用中,这个特性越发明显。
• 可操作的 DOM 结构:SVG 的结构类似于 HTML,具有可操作的 DOM。这意味着用户可以使用代码直接实现想要的矢量图,给 DOM 添加动画,让 SVG 动起来。

SVG DOM

<svg x="0px" y="0px" width="450px" height="100px" viewBox="0 0 450 100" style="border: 1px solid black;">
  <rect x="10" y="5" fill="white" stroke="black" width="90" height="90"></rect>
  <circle fill="black" stroke="black" cx="170" cy="50" r="45"></circle>
  <polygon fill="white" stroke="black" points="279,5 294,35 328,40 303,62 309,94 279,79 248,94 254,62 230,39 263,35">
  </polygon>
  <line fill="none" stroke="black" x1="410" y1="95" x2="440" y2="6"></line>
  <line fill="none" stroke="black" x1="360" y1="6" x2="360" y2="95"></line>
</svg>

我们先看看这个 SVG 结构,由于和 HTML 是相通的,所以 SVG 的语法也是通熟易懂的。在根结点<svg>中,我们看到了 x 和 y 值皆为 0,代表的是 SVG 坐标系统的起始点。同时 width 和 height 都有所指定,并且可以看到他们和 viewBox 的最后两个参数相同。
代码中 rect 表示矩形,circle 表示圆形,cx cy 为圆心坐标,r 为半径,polygon 可随意绘制由各个点 points 连成的图形,line 为线。

ViewBox

SVG 的 viewBox 是一个非常强大的属性,因为他真正的允许 SVG 画布无限延伸,并且同时控制和精确定义 SVG 的可视空间。按照x y width height的顺序,viewBox 有 4个参数需要设置,viewBox 的值不带单位,因为可是空间不是靠像素来定义的,而是一个可任意延展的空间,这样就可以适应许多不同的尺寸。
如上图 1 - 1来看,我们把这个 svg 的背景看成是一张方格纸,基于这张方格定义一个坐标系,这张方格纸本身是自我独立的。我们可以随意修改方格纸的width、height或者任意的事物,都不会影响方格纸上的 svg 本身。我们可以理解为,所有图形都基于 viewBox 的坐标系,并绘制在 viewBox 中,而 viewBox 会自动根据<svg>的宽高来适配。

SVG 动画

CSS 动画

<?xml version="1.0" encoding="UTF-8"?>
<svg id="svg-order" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
    <g id="svg" transform="translate(-266.000000, -59.000000)" fill="#000000">
      <path id="order"></path>
    </g>
  </g>
</svg>
<style>
 #svg-order {
  animation: name 2s infinite ease-in-out forwards;
}
@keyframes name {
  0% {
    transform: translateX(0);
  }
  50% {
    background: greenyellow;
    transform: translateX(100px) scale(2);
  }
  100% {
    background: hotpink;
    transform: translateX(200px);
  }
}
</style>

上面的例子中,通过 CSS 直接操作 DOM,添加 CSS 动画。

序列帧 step 制作动画

animation: splashit 1.8s steps(24) infinite;

SVG 制作的雪碧图,通过 CSS 动画中的 step 序列帧来展示图像,类似动画的制作方法,背景不更换,人物每一帧的运动,就形成一个复杂的动画。

通过第三方框架 GreenSock

<svg width="200px" height="500px" viewBox="0 0 200 500">
  <circle class="element" fill="black" cx="45" cy="45" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="95" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="145" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="195" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="245" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="295" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="345" r="25"></circle>
  <circle class="element" fill="black" cx="45" cy="395" r="25"></circle>
</svg>
<script>
  // TweenMax.to('.element', 2, {x: 100})
  // TweenMax.fromTo('.element', 2, {x: 0}, {x: 100})
  TweenMax.staggerTo('.element', 2, {x: 100}, 0.1)
</script>

通过直接引入 GreenSock ,通过其强大的动画能力直接操作 DOM。上图是一个依次向 x 方向移动 100px的方法。