美文网首页Web前端之路让前端飞程序员
LOL六周年里的按钮动画——处理复杂动画的方式

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

作者: tomfriwel | 来源:发表于2017-09-03 22:21 被阅读892次
    LOL六周年按钮

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


    LOL六周年动画按钮

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

    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: 0 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()
    
    根据@荷塘白露的建议,其实可以通过单纯js来实现动画, 而不需要写那么多CSS
    注意到原图是每排三个,那么我们可以这样写达到同样的效果:
    let div = document.getElementsByClassName('animate_div')[0]
    let i = 0
    
    const run = function () {
        i = i > 23 ? 0 : i+1
        div.style.backgroundPosition = -i%3*280 + 'px ' + -Math.floor(i/3)*90 + 'px'
        setTimeout(run, 50)
    }
    
    run()
    

    纯CSS版

    根据@甜虾的建议,可以使用CSSsteps来实现,这个可能存在兼容问题。纯CSS版本可能有些帧没显示到。

    <html>
        <head>
            <style>
                .animate_div {
                    width: 280px;
                    height: 90px;
                    background-image: url(./images/btn1_sprite.png);
                    background-repeat: no-repeat;
    
                    animation: play_x 300ms steps(3) infinite;
                    animation: play_y 900ms steps(8) infinite;
                }
    
                @keyframes play_x {
                    from {
                        background-position: 0px 0;
                    }
                    to {
                        background-position: -560px 0;
                    }
                }
                @keyframes play_y {
                    from {
                        background-position: 0px 0;
                    }
                    to {
                        background-position: 0 -720px;
                    }
                }
            </style>
        </head>
        <body>
            <div class="animate_div"></div>
        </body>
    </html>
    

    效果图

    效果图

    源代码:
    Github: tomfriwel/lol6anniversary

    参考:
    关于帧数与人眼的问题
    LOL六周年原网页
    CSS3 animation的steps方式过渡

    相关文章

      网友评论

        本文标题:LOL六周年里的按钮动画——处理复杂动画的方式

        本文链接:https://www.haomeiwen.com/subject/yvndjxtx.html