anime.js 实战:SVG clip-path 动画简明教程

1,944 阅读4分钟
原文链接: svgtrick.com

这篇文章来讲讲使用anime.js来操作SVG中的clip-path来实现上图中的动画效果。这个效果灵感来自于Herry Koo的SA 15

准备工作

实现之前,需要先准备一些基本的SVG元素。

1、2个弧形

2、2个矩形clip-path

3、一个圆圈

弧形是圆或椭圆一部分的形状。任何一个从直线或水平上的偏离或弯曲,使其表现为一个圆弧或椭圆弧的形状。一种直观的表示椭圆弧线的方式是,根据椭圆中心 (x, y),x 轴半径 rx,y 轴半径 ry,开始角度 startAngle,结束角度 endAngle。而 SVG 是采取path中的A语法来绘制弧形:

A(a)rx ry x-axis-rotation large-arc-flag sweep-flag x y

下面来分别解释下各个参数的含义:

1、rx和ry分别规定x轴和y轴方向上的半径长度,如果两者相同,那么绘制的是一个正圆,否则是一个椭圆。

2、x-axis-rotation规定圆弧的横轴与坐标系x轴的夹角,正数表示顺时针旋转,负数代表逆时针旋转。

3、large-arc-flag规定绘制较大弧线还是绘制较小弧线;在半径确定的情况下,两点之间绘制一条弧线,弧线的长度会有两种情况;为1表示大角度弧线,0 代表小角度弧线。

4、sweep-flag规定弧线的绘制方向,顺时针或逆时针绘制弧线,1代表顺时针方向,0 代表逆时针方向。

5、x和y规则弧线终点坐标。

根据上面的理论来绘制效果中需要的两个弧形:

<!--
  Move to the starting point then draw an arc to the end point
  and close the shape by going back to the starting point

  M start_x start_y A 113 113 0 large-arc-flag 1 end_x end_y Z
-->
<path class="js-left-slice"
  d="M 441.6 405 A 113 113 0 1 1 441.6 195 Z" />

<path class="js-right-slice"
  d="M 441.6 195  A 113 113 0 0 1 441.6 405 Z" />

对应着上面的理论来解释下第一条path命令的含义:

1、rx和ry的值都是113。

2、x-axis-rotation:旋转0度。

3、large-arc-flag参数值为1,表示绘制较大的弧度。

4、sweep-flag参数值为0,表示顺时针绘制。

5、弧线的重点坐标是(441.6,195)。

效果需要的两个弧形元素就绘制出来了。

源代码地址

从上面的效果可以看到,我们需要把弧形整个都填充满颜色,并且作为clipPath元素来使用。

<defs>
  <clipPath id="left-slice-mask">
    <path d="M 441.6 405 A 113 113 0 1 1 441.6 195 Z" fill="#fff" />
  </clipPath>
  <clipPath id="right-slice-mask">
    <path d="M 441.6 195  A 113 113 0 0 1 441.6 405 Z" fill="#fff" />
  </clipPath>
</defs>
<rect
  class="js-right-fill"
  x="441.6" y="187" width="72" height="226"
  clip-path="url(#right-slice-mask)"
/>

并且在矩形中来引用定义好的clipPath元素,使用animejs来移动矩形的位置,就可以实现下图所示的滑动动画效果。

源代码地址

要实现上下移动的效果也很简单,只需要同时改变矩形的translateXtranslateY就可以了。

源代码地址

接下来来实现小球撞击爆开的效果。其实它就是个圆圈。在初始化的时候,隐藏矩形和蒙版,显示圆圈。当圆圈向右移动的时候使用scaleX来对它进行缩放从而实现这个撞击爆开的效果。

源代码地址

至于抽搐的效果主要是参考了这篇文章里面的实现原理来实现的。也可以看看这篇文章

把这些组合起来就实现了文章刚开始的动画效果。

其实还可以实现更多有趣的动画效果。虽然实现的技术不同,但都是以SVG为基础来实现的。

本文主要是从Animating Clipped Shapes这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!