9

之前做过CSS动画、canvas动画,但svg动画第一次做,最终效果如下图所示。
图片描述

分析

由上图可以看出,波浪动画是由多个不同的‘波浪’组成,而每个波浪则是由近似正弦图形组成,最后的‘波动’效果,其实是静态的波浪循环向左运动产生的。

同时介绍后面会用到的几个svg相关标签:

  • path:定义形状的基础元素,其中d属性就是图形的路径。静态的波浪就是这个元素绘制的,后面会再单独介绍

  • animateTransform:定义目标元素的变形属性,波浪的循环移动就是使用这个属性实现的

  • g:组合对象的容器

绘制单个静态波浪

 <svg
    xmlns="http://www.w3.org/2000/svg"         
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <path
        d="
            M0 70
            Q 75 39, 150 70
            T 300 70 
            V 100 H 0 V 0"
        fill="#ccc">
    </path>
</svg> 

上面是写好的单个波浪,其中d属性绘制了形状,fill属性表示填充的颜色。

d属性中使用了以下几个命令:

M:M x y表示移动到(x, y)点( svg中左上角是(0,0)点 )
Q:Q x1 y1, x2 y2表示绘制二次贝塞尔曲线,x1 y1为二次贝塞尔的控制点,x2 y2为终点,可以使用贝塞尔生产曲线工具帮助生成。
T:T x y表示生成上一个二次贝塞尔曲线的镜像,其终点坐标为(x,y)
V:V y表示从当前点(x0,y0)垂直移动到(x0, y)
H:H x表示从当前点(x0, y0)水平移动到(x, y0)

所以上面代码可以翻译后为:首先移动到(0,70)处,再绘制起点为(0,70),终点为(150,70),控制点为(75,39)的二次贝塞尔曲线,接着绘制已(300,70)为终点的镜像二次贝塞尔曲线,最后依次移动到(100,70),(0,70),(0,0),从而形成闭合曲线。

动起来

<svg
    xmlns="http://www.w3.org/2000/svg"     
    xmlns:xlink="http://www.w3.org/1999/xlink"
    width="300"
    height="200">
    <g >
        <path
            d="M 0 70 Q 75 39, 150 70 T 300 70 T 450 70 T 600 70 T 750 70 V 100 H 0 V 0"
            fill="#ccc">
        </path>
        <animateTransform
            attributeName="transform"
            attributeType="XML"
            type="translate"
            from="0" to="-300" dur="1.5s" 
            repeatCount="indefinite">
        </animateTransform>
    </g>
</svg> 

增加了animateTransform后就动其来了,该标签的几个属性含义为:

attributeName:需要运动的属性
type:具体运动的类型
from:运动初始值
to:运动终点值
dur:运动时间
repeatCount:重复次数,indefinite为无限循环

看了后就发现其实很简单,有一下几个点需要注意,首先path绘制图形的路径至少是svg宽加上from-to的宽,第二,to的值为周期的n/2倍,这个可以想象一下正弦的波形。注意了这两点,波浪看起来已经有点模样了。

多个波浪合成

只有一个波浪,看起来还是不够逼真,将多个不同周期波浪合成,并填充不同透明度的颜色形成最终效果。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="200">
    <g fill="rgba(106,127,239,0.1)">
        <path d="M 0 70 Q 75 39, 150 70 T 300 70 T 450 70 T 600 70 T 750 70 V 100 H 0 V 0"></path>
        <animateTransform attributeName="transform" attributeType="XML" type="translate" from="0" to="-300" dur="1.5s" repeatCount="indefinite"></animateTransform>
    </g>
    <g fill="rgba(106,127,239,0.15)">
        <path d="M 0 70 Q 87.5 47, 175 70 T 350 70 T 525 70 T 700 70 T 875 70 T 1050 70 V 100 H 0 V 0"></path>
        <animateTransform attributeName="transform" attributeType="XML" type="translate" from="0" to="-350" dur="3s" repeatCount="indefinite"></animateTransform>
    </g>
    <g fill="rgba(106,127,239,0.18)" transform="translate(-903.868 0)">
        <path d="M 0 70 Q 135 36, 270 70 T 540 70 T 810 70 T 1080 70 V 100 H 0 V 0" transform="translate(-38.232284367796474, 0)"></path>
        <animateTransform attributeName="transform" attributeType="XML" type="translate" from="0" to="-540" dur="2s" repeatCount="indefinite"></animateTransform>
    </g>
</svg> 

抽象成组件

当手写两个波浪之后,就会发现很多地方是相同的,总结之后会发现只有svg的宽高、周期、峰值、移动速度、初始偏移量(即正弦的初相位)、填充颜色、叠加波浪个数这几个是变化的,因此可以做成组件,隐藏内部的复杂度。


kjnt
275 声望5 粉丝

悟已往之不谏,知来者之可追。