LOL六周年里的按鈕動(dòng)畫(huà)——處理復(fù)雜動(dòng)畫(huà)的方式

LOL六周年按鈕

最近LOL六周年官網(wǎng)網(wǎng)頁(yè)得到了更新,里面出現(xiàn)了這樣的一個(gè)動(dòng)畫(huà):


LOL六周年動(dòng)畫(huà)按鈕

我看這個(gè)動(dòng)畫(huà)挺有意思的,想看看是怎么做的,就通過(guò)檢查元素看了下。
本來(lái)以為是通過(guò)canvas做的,沒(méi)想到看到了這樣的背景圖:

LOL六周年按鈕動(dòng)畫(huà)背景圖

其原理就是一幀一幀的變化,就像做動(dòng)畫(huà)一樣。

動(dòng)畫(huà)原理

動(dòng)畫(huà)是通過(guò)連續(xù)播放一系列靜止的畫(huà)面,當(dāng)連續(xù)播放達(dá)到一定的速度時(shí),我們用肉眼看到的就是動(dòng)畫(huà)了。它的基本原理與電影,電視一樣,都是利用視覺(jué)原理。醫(yī)學(xué)已經(jīng)證明,人的眼睛具有“視覺(jué)暫留”特性,就是人的眼睛看到一幅畫(huà)面或一個(gè)物體后,在1/24秒內(nèi)不會(huì)消失,利用這一視覺(jué)變化效果。因此電影采用了每秒24幅畫(huà)的速度拍攝播放,電視采用了每秒25幅(PAL制)或30幅(NSTC制)畫(huà)面的速度拍攝播放,如果以每秒低于24幅畫(huà)面的速度拍攝播放,就會(huì)出現(xiàn)停頓現(xiàn)象。
幀頻:即每秒播放的幀數(shù)。幀頻的大小直接影響到動(dòng)畫(huà)的快慢。幀頻的單位是“幀/秒”,即“fps”,flash中默認(rèn)為12fps.由于計(jì)算機(jī)顯示器的熒光刷新特性,實(shí)際看到的相當(dāng)于24幀,剛好達(dá)到了動(dòng)畫(huà)的一般要求。

仔細(xì)一想,的確,要實(shí)現(xiàn)這樣的動(dòng)畫(huà),感覺(jué)真的很難,太費(fèi)時(shí)間了。
對(duì)于很復(fù)雜的動(dòng)畫(huà),完全可以把動(dòng)畫(huà)截成一幀一幀的圖片,然后通過(guò)一定的速度去更替。

下面是這個(gè)動(dòng)畫(huà)的代碼:

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;
}

/*下面這部分是直接復(fù)制的原網(wǎng)頁(yè)的*/
.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

// 每隔一段時(shí)間更換背景圖
const run = function () {
    if (i > 25) {
        i = 1
    }

    div.classList.remove(className)  //移除之前的背景類
    className = 'ans_btn' + i
    div.classList.add(className)  //添加當(dāng)前背景類

    i++

    setTimeout(run, 50)
}

run()
根據(jù)@荷塘白露的建議,其實(shí)可以通過(guò)單純js來(lái)實(shí)現(xiàn)動(dòng)畫(huà), 而不需要寫(xiě)那么多CSS。
注意到原圖是每排三個(gè),那么我們可以這樣寫(xiě)達(dá)到同樣的效果:
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版

根據(jù)@甜蝦的建議,可以使用CSSsteps來(lái)實(shí)現(xiàn),這個(gè)可能存在兼容問(wèn)題。純CSS版本可能有些幀沒(méi)顯示到。

<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

參考:
關(guān)于幀數(shù)與人眼的問(wèn)題
LOL六周年原網(wǎng)頁(yè)
CSS3 animation的steps方式過(guò)渡

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,111評(píng)論 25 709
  • 動(dòng)畫(huà),顧名思義,就是能“動(dòng)”的畫(huà)。人的眼睛對(duì)圖像有短暫的記憶效應(yīng),所以當(dāng)眼睛看到多張圖片連續(xù)快速的切換時(shí),就會(huì)被認(rèn)...
    彬_仔閱讀 1,756評(píng)論 1 8
  • 什么是動(dòng)畫(huà)動(dòng)畫(huà),顧名思義,就是能“動(dòng)”的畫(huà)。人的眼睛對(duì)圖像有短暫的記憶效應(yīng),所以當(dāng)眼睛看到多張圖片連續(xù)快速的切換時(shí)...
    M_慕宸閱讀 3,641評(píng)論 0 6
  • 在建筑工程中,鋼筋一般的加工過(guò)程包括了除銹、調(diào)直、剪切、彎曲等。 1、鋼筋除銹方法 鋼筋除銹的方法也有多種,合理的...
    工程寶閱讀 9,563評(píng)論 0 1
  • 現(xiàn)在隨便點(diǎn)開(kāi)某個(gè)求職網(wǎng)站,就會(huì)有“大學(xué)生兼職”的專欄,聘用崗位涉及行業(yè)之多,門(mén)類之全。似乎大學(xué)生已是用人單位不可或...
    Starwarming閱讀 591評(píng)論 0 1

友情鏈接更多精彩內(nèi)容