Css3幀動畫深入探尋,講點專案中實際會碰到的問題

池中物willian發表於2015-09-22

先加個副標題XD

--如何解決background-size為100%下處理@keyframes

正是在專案中遇到副標題,才引起我更深入的探尋

 

先略帶一下基本的css3動畫


 

css3的動畫實現是通過屬性animation 與 @keyframes配合實現的

具體可以參見這篇文章,這位女程式媛有著非常詳盡與精彩的闡述

https://24ways.org/2012/flashless-animation/

最後實現了一張貓跑動在有視訊滾動的畫面上 

 

為什麼不用gif?

gif動畫就是典型的幀動畫,gif在各瀏覽器上也支援的很好。手機上表現也很好。

唯一的缺點就是體積太大,繼而導致低端機上吃記憶體卡頓。

 

用css3來實現動畫,會明顯降低圖片體積,即用sprite形式

 

通常,網上文章介紹的動畫都是用px做為大小或距離單位

 

css3的動畫實現是通過屬性animation 與 @keyframes配合實現的

具體可以參見這篇文章,這位女程式設計師有著非常詳盡與精彩的闡述

https://24ways.org/2012/flashless-animation/

最後實現了一張貓跑動在有視訊滾動的畫面上

 

通常,網上文章介紹的動畫都是用px做為大小或距離單位

@keyframes walk-cycle {  
    0% {background-position: 0 0; }
    100% {background-position: -880px  0;}
}

動畫實現如:

.anim-div{
    background-image: “那個蛋的圖地址”
    animation: walk-cycle 1s steps(11) infinite;

}

以上就是最簡單實現幀動畫的程式碼了..

嗯。。在pc上看起來貌似還行。

 

實際專案中遇到的問題。


 

如果是在手機上,

為簡單的適應不同螢幕尺寸,我們通常的做法是讓美工大人出一張相對比較大的圖,比如以iphone5為基準,320px寬度。

讓美工提供640寬度的圖給我們。我們通過設定background-size: 100%即可等比縮放來適應大部分的屏了,而不必為每個螢幕都設定不同的背景圖片。

那麼就成了以下的程式碼

.anim-div{
    background-image: “那個蛋的圖地址”
    background-size: 100%
    animation: walk-cycle 1s steps(11) infinite;
}

對,就加了一句background-size: 100%

結果就是,蒙逼了。。動畫完全不像預想的那樣浪了。現在真是浪出新風格了..

 

搜了半天google才找到有類似的回答,然後解決方法是

@keyframes walk-cycle {  
    0% {background-position: 0 0; }
    100% {background-position: 110%  0;}
}
.anim-div{
    background-image: “那個蛋的圖地址”
    background-size: 1100%
    animation: walk-cycle 1s steps(11) infinite;
}

第一步:background-size設定為幀數*100%,即1100%

第二步:讓關鍵幀也變換為百分比, 並且為其補上最後一幀

 

公式為:  ((100/(2-1)) + 100) /100

公式為:  ((100/(2-1)) + 100) /100

公式為:  ((100/(2-1)) + 100) /100

重要的話說三遍,所以公式寫三遍

 

此例子中即:

(100 / (11-1) +100)  / 100 = 1.1

background-position: 110%  0;

 

為什麼要補上一幀?


 

帶出了另一個話題

在做biu動圖社群HTML5展示頁時,偶然發現keyframe實現的動圖迴圈過程中會丟失一幀,找了好久終於有一篇國外同行研究此現象的文章,

 

當使用css3的steps配合以百分比為值的background-position時,迴圈幀的過程中最後一幀是不顯示的

 

以下是我找到的國外網友分析的資料及例項測試,例項中檢視原始碼即可看到以下的分析邏輯

寫的測試地址:

http://willian12345.github.io/test-demo/step-keyframes/

http://sheldonwang.com/test-demo/step-keyframes/

 

接下來分析一下:

 

@keyframes countdown { 

0% { background-position: 0 0; } 

100% {background-position: 0 100%; } 

}
.flick {

animation: countdown 1s steps(2) infinite;

background: url(1-2.png) 0 0 no-repeat;

}

 

你以為.flick就可以讓動畫在1和2之間跳動形成動畫

然而並沒有,它只是在1和2中間一半處移來移去

讓我們試試加上”end”或“start”屬性,看看行不行

.flick-end {

animation: countdown 1s steps(1, end) infinite;

}



.flick-start {

animation: countdown 1s steps(1, start) infinite;

}

它們看起來直接跳過了開始或結束那一幀

 

綜合查閱了相關資料,end和start控制的是一個幀迴圈結束後連線上繼續迴圈的是哪一幀,現象是

如果設定的是end,那麼最後一幀就被無視掉了,如果設定的是start,那麼第一幀被無視了。W3c有個相應說明的圖,反正我是沒看明白。

 

讓我們用3幀的圖來驗證一下

.easy-as {

animation: countdown 1s steps(2, end) infinite;

background: url(1-2-3.png) 0 0 no-repeat;

}

果然end效果是1與2之反覆跳轉,直接無視了3

 

 

要讓它正常依次顯示1,2,3那麼需要補上一幀

@keyframes countdownTo3 { 

0% { background-position: 0 0; } 

100% {background-position: 0 150%; } 

}



.easy-working {

animation: countdownTo3 1s steps(3) infinite;

}

設為150%,即補上了50%一格的高度(一幀)

 

所以當為兩幀時

@keyframes countdownTo2 { 

0% { background-position: 0 0; } 

100% {background-position: 0 200%; } 

}



.flick-working {

animation: countdownTo2 1s steps(2) infinite;

}

再用公式算一遍

background-position-y: (100 / (2-1) +100)  / 100  = 200%

嗯,所以是y軸上是200%    即:   background-position: 0 200%;

 

結束語


一開始還真沒注意過這些小細節,直到寫到才會碰到,碰到再解決。。so,只能說能多寫就多寫嘍

直到財務自由!!!,財務自由!!!,財務自由!!!重要的話說三遍

祝看到這篇文章的小夥伴都能實現

 

=================================================傲嬌分割線===============================================

轉載註明,部落格園

willian12345@126.com

sheldon.wang

github.com/willian12345

 

相關文章