CSS3動畫幀數科學計演算法
阿新 • • 發佈:2019-02-05
迴圈動畫按迴圈方式可以分為:
用CSS程式碼的方式表示,就是:
單向迴圈: animation-iteration-count: infinite; animation-direction: normal;
雙向迴圈: animation-iteration-count: infinite; animation-direction: alternate;
先看看做一個動畫需要哪些條件
總幀數:100 (已知引數)
CSS3幀動畫的幀數設定是從0%~100%,數值可以帶小數位,0%可以用from關鍵詞替代,100%可以用to關鍵詞替代
動作數:n (已知引數)
動畫中的幾個關鍵動作
動作停留幀數:x (未知引數)
在當前動作停留的幀數
動作過渡幀數:y (未知引數)
上一個動作過渡到下一個動作需要用的幀數
我們用示例來說明它們之間的關係。
單向迴圈動畫
示例要求:實現一個3個動作的單向迴圈動畫
為了方便理解,以線段圖示法來展示
Step1,滿幀100%
0% 100%
└─────────────────────────────────────────┘
Step2,新增動作節點(總節點數 = 動作數)
0% ?% 100%
過渡y幀 過渡y幀 └────────────────────┴────────────────────┘
動作1 動作2 動作3
動作1 動作2 動作3
這下就複雜了,不過我們仔細分析,會發現它們之間有一定的規律。
3x + 2y = 100
動作個數 = 3 停留幀個數 = 3 過渡幀個數 = 2
設動作個數為n,則
動作個數 = n 停留幀個數 = n 過渡幀個數 = n-1
然後,我們可以得出一個公式
nx + (n-1)y = 100 接下來我們可以有規則性的嘗試動畫引數了,我們嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y也等於20,於是得出我們的幀數程式碼
雙向迴圈動畫
示例要求:實現一個3個動作的雙向迴圈動畫
複製上面的動畫程式碼,加個 animation-direction: alternate; 屬性不就好了?
(哦,不對,按照心理學反推論,如果這麼簡單,作者有必要另起篇幅嗎?肯定有陰謀!)
不用猜了,我就是有陰謀!
繼續線段圖示,當我們加入 animation-direction: alternate; 屬性之後的效果是
問題:首尾動作從第二遍播放開始會重複停留時間!
這個並不是我們期望看到的效果,不過解決方法也很簡單
通過線段圖分析
2x + 2y = 100 動作個數 = 3 停留幀個數 = 2 過渡幀個數 = 2
設動作個數為n,則
動作個數 = n 停留幀個數 = n-1 過渡幀個數 = n-1
然後,我們可以得出一個公式
(n-1)(x+y) = 100
接下來我們還是嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y等於30,於是得出我們的幀數程式碼
細心的同學會發現,其實這裡還有點小瑕疵,那就是
問題:第一次播放的第一個動作只停了一半時間!
有時我們做動作銜接,一定要所有動作時間都保持一致。解決辦法也不是沒有,可以給動畫加個延遲時間 animation-delay 屬性,時長等於動作停留時間的一半,如何計算時長後面會講到。
除了加延時解決這個問題之外,還有一個偽方法,請繼續往下看
模擬雙向迴圈動畫
示例要求:實現一個3個動作的雙向迴圈動畫
模擬雙向迴圈動畫就是不使用 animation-direction: alternate; 屬性實現雙向迴圈的效果。
有點繞,上線段圖
通過線段圖分析
4x + 4y = 100 動作個數 = 5 停留幀個數 = 4 過渡幀個數 = 4
設動作個數為n,則
動作個數 = n 停留幀個數 = n-1 過渡幀個數 = n-1
然後,我們可以得出一個公式
(n-1)(x+y) = 100
但動作個數5包含了重複動作,不符合我們的計算習慣,不包含重複動作個數3才符合我們的計算習慣。那麼設
(不含重複)動作個數為 m
(含重複)動作個數為 n,則 n = 2m-1,將 2m-1 帶入上面的公式得出公式
(2m-1-1)(x+y) = 100
將m統一換成n表示,再簡化公式後得到最終公式
(2n-2)(x+y) = 100
接下來我們再次嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y等於5,於是得出我們的幀數程式碼
提到延遲播放,跟時間有關係,這個延遲時長該怎麼定?如果以上方案,每個動作我們要固定它的過渡時間,比如動作之間過渡0.4秒,那過渡幀數又該怎麼定?接下來我們再挖掘一下,幀數如何跟時間結合。
時間模式計算幀數
我們在做動畫的時候需要設定一個 animation-duration 動畫持續時間的屬性,知道持續播放時間我們就可以很輕易的計算出播放速度,還記得我們小學學的速度公式嗎?
設,總幀數為s(100幀),播放時間為t,播放速度為v,得出公式
v = s / t
繼續用示例來加深理解。
示例要求:實現一個3個動作的單向迴圈動畫,播放時間2秒,每個動作的過渡時間為0.4秒
通過播放速度公式,我們可以計算出過渡幀數。
播放速度: 100幀 / 2秒 = 50幀/秒
過渡幀數: 50幀/秒 * 0.4秒 = 20幀
得出過渡幀數,接下來套用單向迴圈動畫的幀數公式,計算出停留幀數,參考上面總結的公式 nx + (n-1)y = 100 ,推導公式得出停留幀數 x = (100-(n-1)y) / n
動作個數(n): 3
過渡幀數(y): 20
停留幀數: (100-(3-1)*20)/3 = 20幀
於是得出我們的幀數程式碼
CSS3動畫幀數計算器:http://tid.tenpay.com/labs/css3_keyframes_calculator.html
以白樹同學的跑步動畫為示例
動畫是單向迴圈,有7個關鍵動作,動作需要使用逐幀過渡效果 animation-timing-function:step-start 實現,所以動作個數需要額外加1,即有8個動作。使用 step-start 後會自動平分動作停留時間,所以keyframes我們就不用加動作停留幀數了。
開啟工具頁面,選擇 [單向迴圈動畫] -> [不停頓] -> [動作個數8] -> [生成程式碼]
用CSS程式碼的方式表示,就是:
單向迴圈: animation-iteration-count: infinite; animation-direction: normal;
雙向迴圈: animation-iteration-count: infinite; animation-direction: alternate;
先看看做一個動畫需要哪些條件
總幀數:100 (已知引數)
CSS3幀動畫的幀數設定是從0%~100%,數值可以帶小數位,0%可以用from關鍵詞替代,100%可以用to關鍵詞替代
動作數:n (已知引數)
動畫中的幾個關鍵動作
動作停留幀數:x (未知引數)
在當前動作停留的幀數
動作過渡幀數:y
上一個動作過渡到下一個動作需要用的幀數
我們用示例來說明它們之間的關係。
單向迴圈動畫
示例要求:實現一個3個動作的單向迴圈動畫
為了方便理解,以線段圖示法來展示
Step1,滿幀100%
0% 100%
└─────────────────────────────────────────┘
Step2,新增動作節點(總節點數 = 動作數)
0% ?% 100%
過渡y幀 過渡y幀 └────────────────────┴────────────────────┘
動作1 動作2 動作3
這個時候,我們很輕易的算出動作2的keyframes幀數是50%
實際上,很多時候我們需要讓每個動作停頓一會,而不會閃動太快。如“嘀卡萌風騷亂舞”的動畫,每個動作都需要定格一會,這個時候我們需要給每個動作分配一些停留幀數。
Step3,新增停留幀 (總節點數 = 動作數 * 2)
0% ?% ?% ?% ?% 100%
動作1 動作2 動作3
這下就複雜了,不過我們仔細分析,會發現它們之間有一定的規律。
3x + 2y = 100
動作個數 = 3 停留幀個數 = 3 過渡幀個數 = 2
設動作個數為n,則
動作個數 = n 停留幀個數 = n 過渡幀個數 = n-1
然後,我們可以得出一個公式
nx + (n-1)y = 100 接下來我們可以有規則性的嘗試動畫引數了,我們嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y也等於20,於是得出我們的幀數程式碼
- .demo{animation:anim-name 1s infinite;} /* 單向迴圈 */
- @keyframes anim-name{
- 0%, 20%{ /* 動作1 */ }
- 40%, 60%{ /* 動作2 */ }
- 80%, 100%{ /* 動作3 */ }
- }
雙向迴圈動畫
示例要求:實現一個3個動作的雙向迴圈動畫
複製上面的動畫程式碼,加個 animation-direction: alternate; 屬性不就好了?
(哦,不對,按照心理學反推論,如果這麼簡單,作者有必要另起篇幅嗎?肯定有陰謀!)
不用猜了,我就是有陰謀!
繼續線段圖示,當我們加入 animation-direction: alternate; 屬性之後的效果是
問題:首尾動作從第二遍播放開始會重複停留時間!
這個並不是我們期望看到的效果,不過解決方法也很簡單
通過線段圖分析
2x + 2y = 100 動作個數 = 3 停留幀個數 = 2 過渡幀個數 = 2
設動作個數為n,則
動作個數 = n 停留幀個數 = n-1 過渡幀個數 = n-1
然後,我們可以得出一個公式
(n-1)(x+y) = 100
接下來我們還是嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y等於30,於是得出我們的幀數程式碼
- .demo{animation:anim-name 1s infinite alternate;} /* 雙向迴圈 */
- @keyframes anim-name{
- 0%, 10%{ /* 動作1 */ }
- 40%, 60%{ /* 動作2 */ }
- 90%, 100%{ /* 動作3 */ }
- }
細心的同學會發現,其實這裡還有點小瑕疵,那就是
問題:第一次播放的第一個動作只停了一半時間!
有時我們做動作銜接,一定要所有動作時間都保持一致。解決辦法也不是沒有,可以給動畫加個延遲時間 animation-delay 屬性,時長等於動作停留時間的一半,如何計算時長後面會講到。
除了加延時解決這個問題之外,還有一個偽方法,請繼續往下看
模擬雙向迴圈動畫
示例要求:實現一個3個動作的雙向迴圈動畫
模擬雙向迴圈動畫就是不使用 animation-direction: alternate; 屬性實現雙向迴圈的效果。
有點繞,上線段圖
通過線段圖分析
4x + 4y = 100 動作個數 = 5 停留幀個數 = 4 過渡幀個數 = 4
設動作個數為n,則
動作個數 = n 停留幀個數 = n-1 過渡幀個數 = n-1
然後,我們可以得出一個公式
(n-1)(x+y) = 100
但動作個數5包含了重複動作,不符合我們的計算習慣,不包含重複動作個數3才符合我們的計算習慣。那麼設
(不含重複)動作個數為 m
(含重複)動作個數為 n,則 n = 2m-1,將 2m-1 帶入上面的公式得出公式
(2m-1-1)(x+y) = 100
將m統一換成n表示,再簡化公式後得到最終公式
(2n-2)(x+y) = 100
接下來我們再次嘗試讓每個動作停留20幀,通過公式求得動作過渡幀數y等於5,於是得出我們的幀數程式碼
- .demo{animation:anim-name 1s infinite;} /* 模擬雙向迴圈 */
- @-webkit-keyframes anim-name{
- 0%{ /* 動作1 */ }
- 20%{ /* 動作1 */ }
- 25%{ /* 動作2 */ }
- 45%{ /* 動作2 */ }
- 50%{ /* 動作3 */ }
- 70%{ /* 動作3 */ }
- 75%{ /* 動作2 */ }
- 95%{ /* 動作2 */ }
- 100%{ /* 動作1 */ }
- }
- .demo{animation:anim-name 1s infinite;} /* 模擬雙向迴圈 */
- @keyframes anim-name{
- 0%, 20%, 100%{ /* 動作1 */ }
- 25%, 45%, 75%, 95%{ /* 動作2 */ }
- 50%, 70%{ /* 動作3 */ }
- }
提到延遲播放,跟時間有關係,這個延遲時長該怎麼定?如果以上方案,每個動作我們要固定它的過渡時間,比如動作之間過渡0.4秒,那過渡幀數又該怎麼定?接下來我們再挖掘一下,幀數如何跟時間結合。
時間模式計算幀數
我們在做動畫的時候需要設定一個 animation-duration 動畫持續時間的屬性,知道持續播放時間我們就可以很輕易的計算出播放速度,還記得我們小學學的速度公式嗎?
設,總幀數為s(100幀),播放時間為t,播放速度為v,得出公式
v = s / t
繼續用示例來加深理解。
示例要求:實現一個3個動作的單向迴圈動畫,播放時間2秒,每個動作的過渡時間為0.4秒
通過播放速度公式,我們可以計算出過渡幀數。
播放速度: 100幀 / 2秒 = 50幀/秒
過渡幀數: 50幀/秒 * 0.4秒 = 20幀
得出過渡幀數,接下來套用單向迴圈動畫的幀數公式,計算出停留幀數,參考上面總結的公式 nx + (n-1)y = 100 ,推導公式得出停留幀數 x = (100-(n-1)y) / n
動作個數(n): 3
過渡幀數(y): 20
停留幀數: (100-(3-1)*20)/3 = 20幀
於是得出我們的幀數程式碼
- .demo{animation:anim-name 2s infinite;} /* 單向迴圈 */
- @keyframes anim-name{
- 0%, 20%{ /* 動作1 */ }
- 40%, 60%{ /* 動作2 */ }
- 80%, 100%{ /* 動作3 */ }
- }
CSS3動畫幀數計算器:http://tid.tenpay.com/labs/css3_keyframes_calculator.html
以白樹同學的跑步動畫為示例
動畫是單向迴圈,有7個關鍵動作,動作需要使用逐幀過渡效果 animation-timing-function:step-start 實現,所以動作個數需要額外加1,即有8個動作。使用 step-start 後會自動平分動作停留時間,所以keyframes我們就不用加動作停留幀數了。
開啟工具頁面,選擇 [單向迴圈動畫] -> [不停頓] -> [動作個數8] -> [生成程式碼]