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

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

其原理就是一幀一幀的變化,就像做動(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ù)@甜蝦的建議,可以使用CSS的steps來(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ò)渡