LOL六周年里的按钮动画——处理复杂动画的方式

1,345 阅读3分钟
原文链接: www.jianshu.com
LOL六周年按钮
LOL六周年按钮

最近LOL六周年官网网页得到了更新,里面出现了这样的一个动画:


LOL六周年动画按钮
LOL六周年动画按钮

我看这个动画挺有意思的,想看看是怎么做的,就通过检查元素看了下。
本来以为是通过canvas做的,没想到看到了这样的背景图:

LOL六周年按钮动画背景图
LOL六周年按钮动画背景图

其原理就是一帧一帧的变化,就像做动画一样。

动画原理

动画是通过连续播放一系列禁止的画面,当连续播放达到一定的速度时,我们用肉眼看到的就是动画了。它的基本原理与电影,电视一样,都是利用视觉原理。医学已经证明,人的眼睛具有“视觉暂留”特性,就是人的眼睛看到一幅画面或一个物体后,在1/24秒内不会消失,利用这一视觉变化效果。因此电影采用了每秒24幅画的速度拍摄播放,电视采用了每秒25幅(PAL制)或30幅(NSTC制)画面的速度拍摄播放,如果以每秒低于24幅画面的速度拍摄播放,就会出现停顿现象。 帧频:即每秒播放的帧数。帧频的大小直接影响到动画的快慢。帧频的单位是“帧/秒”,即“fps”,flash中默认为12fps.由于计算机显示器的荧光刷新特性,实际看到的相当于24帧,刚好达到了动画的一般要求。

仔细一想,的确,要实现这样的动画,感觉真的很难,太费时间了。 对于很复杂的动画,完全可以把动画截成一帧一帧的图片,然后通过一定的速度去更替。

下面是这个动画的代码:

HTML

<html>
  <body>
    <div class="animate_div"></div>
  </body>
</html>

CSS

.animate_div {
    width: 280px;
    height: 90px;
    background-image: url(./images/btn1_sprite.png);
    background-repeat: no-repeat;
}

/*下面这部分是直接复制的原网页的*/
.animate_div.ans_btn1 {
    background-position: -280px 0;
}

.animate_div.ans_btn2 {
    background-position: -280px 0;
}

.animate_div.ans_btn3 {
    background-position: -560px 0;
}

.animate_div.ans_btn4 {
    background-position: 0 -90px;
}

.animate_div.ans_btn5 {
    background-position: -280px -90px;
}

.animate_div.ans_btn6 {
    background-position: -560px -90px;
}

.animate_div.ans_btn7 {
    background-position: 0 -180px;
}

.animate_div.ans_btn8 {
    background-position: -280px -180px;
}

.animate_div.ans_btn9 {
    background-position: -560px -180px;
}

.animate_div.ans_btn10 {
    background-position: 0 -270px;
}

.animate_div.ans_btn11 {
    background-position: -280px -270px;
}

.animate_div.ans_btn12 {
    background-position: -560px -270px;
}

.animate_div.ans_btn13 {
    background-position: 0 -360px;
}

.animate_div.ans_btn14 {
    background-position: -280px -360px;
}

.animate_div.ans_btn15 {
    background-position: -560px -360px;
}

.animate_div.ans_btn16 {
    background-position: 0 -450px;
}

.animate_div.ans_btn17 {
    background-position: -280px -450px;
}

.animate_div.ans_btn18 {
    background-position: -560px -450px;
}

.animate_div.ans_btn19 {
    background-position: 0 -540px;
}

.animate_div.ans_btn20 {
    background-position: -280px -540px;
}

.animate_div.ans_btn21 {
    background-position: -560px -540px;
}

.animate_div.ans_btn22 {
    background-position: 0 -630px;
}

.animate_div.ans_btn23 {
    background-position: -280px -630px;
}

.animate_div.ans_btn24 {
    background-position: -560px -630px;
}

.animate_div.ans_btn25 {
    background-position: 0 -720px;
}

JavaScript

let i = 1
let div = document.getElementsByClassName('animate_div')[0]
let className = 'ans_btn' + i

// 每隔一段时间更换背景图
const run = function () {
    if (i > 25) {
        i = 1
    }

    div.classList.remove(className)  //移除之前的背景类
    className = 'ans_btn' + i
    div.classList.add(className)  //添加当前背景类

    i++

    setTimeout(run, 50)
}

run()

效果图

效果图
效果图

参考:
关于帧数与人眼的问题
LOL六周年原网页