一.CSS 動畫
CSS 動畫相對 JS 動畫有 2 個主要優勢:
1.流暢
因為渲染引擎可以透過跳影格(frame-skipping)及其它技術來確保效能盡量流暢
2.瀏覽器效能優化
把動畫序列交給瀏覽器去控制,這樣瀏覽器就能優化效能和效率,比如對於看不見的 tab,可以減少刷新頻率
定義動畫分為 2 部分
-
配置
animation各項子屬性 -
透過
@keyframes定義關鍵影格樣式
瀏覽器根據這些東西來建立補間動畫,計算插值把各個關鍵影格連接起來
二.animation 子屬性
animation-name @keyframes 定義的關鍵影格名,預設 none
animation-duration 動畫時長,預設 0s,與 transition 完全一致
animation-timing-function easying 函數,預設 ease,與 transition 完全一致
animation-delay 延遲時間,預設 0s,,與 transition 完全一致
animation-iteration-count 重複次數,預設 1
animation-direction 方向,預設 normal
animation-fill-mode 樣式套用模式,預設 none
animation-play-state 用來暫停/恢復動畫序列,預設 running
需要注意:
-
先
duration後delay,其它參數順序隨意 -
animation-name不要和關鍵字重名,會優先比對屬性
animation-iteration-count
animation-iteration-count = infinite | <number>
動畫重複次數,各值分別表示無限次、指定次數
animation-direction
animation-direction = normal | reverse | alternate | alternate-reverse
動畫執行方向,各值分別表示正向、反向、交替(奇數次正向偶數次反向)、反向交替(奇數次反向偶數次正向)
animation-fill-mode
animation-fill-mode = none | forwards | backwards | both
樣式套用模式,各值分別表示不套用關鍵影格樣式、(結束後)套用終態樣式、(delay 期間)套用初態樣式、(delay 期間)套用初態樣式且(結束後)套用終態樣式
注意:初態和終態可能是 0% 也可能是 100%,由 animation-iteration-count 和 animation-direction 共同決定
關鍵字含義如下:
none 在動畫結束後,去掉 @keyframes 定義的樣式,恢復原樣式
forwards 在動畫結束後,保持終態樣式
backwards 在動畫開始前(delay 期間),保持初態樣式
both 同時具有 forwards 和 backwards 的效果,即在 delay 期間保持初態樣式,在動畫結束後保持終態樣式
具體差異見 Demo:http://www.ayqy.net/temp/animation/animation-fill-mode.html,點擊紅色塊開始動畫
animation-play-state
animation-play-state = running | paused
決定動畫執行還是暫停,可以用來控制動畫暫停/恢復,比 delay 更強大更靈活一些
具體效果見 Demo:http://www.ayqy.net/temp/animation/animation-play-state.html
三.@keyframes
語法如下:
@keyframes anmiationName {
0% {}
/*...*/
100% {}
}
如果沒有定義 0% 和 100%,瀏覽器就根據其它時刻的關鍵影格給所有屬性算一組值
P.S. to 和 from 分別是 0% 和 100% 的別名,因為初態和終態比較重要,有權申請英文名
四.事件
transition 只有一個 end 事件,animation 提供了 3 個事件:
animationstart 開始
animationend 結束
animationiteration 開始下一次重複
事件物件有 3 個特殊屬性:
-
animationName
即
animation-name -
elapsedTime
單位是秒,對於
animationstart和animationend表示動畫執行到此刻的時間,對於animationiteration,表示下一次重複開始的時間,與transitionend事件類似,一般不受 delay 影響特殊的,
animationstart中的elapsedTime一般為0,除非animation-delay是個負值,此時elapsedTime為-1 * delay -
pseudoElement
以
::開頭的偽元素名,如果動畫不是套用在偽元素上,就是空字串
注意:最後一次重複結束的時候,不會觸發 animationiteration,而是觸發 animationend
五.技巧
1.steps(1) 去掉平滑過渡
steps(1) 與 linear 很像,去掉一個 linear 動畫的補間過渡,只留下關鍵影格,關鍵影格之間的影格延續上一個關鍵影格,就得到了 steps(1)
製作 Flash 時,先插入兩個關鍵影格,此時兩個關鍵影格之間的都是普通影格(用來延長上一個關鍵影格的播放時間),這時的效果就是 steps(1)。右鍵後一個關鍵影格,建立補間動畫,此時得到的就是 linear 效果
實例如下:
.rgb {
-webkit-animation: rgb 1.5s linear infinite;
animation: rgb 1.5s linear infinite;
}
@keyframes rgb {
0% {
opacity: red;
}
33% {
background: green;
}
66% {
background: blue;
}
}
效果是背景色紅綠藍平滑漸變,想去掉漸變的平滑過渡,直接把 linear 改為 steps(1) 即可,如下:
.rgb-step {
-webkit-animation: rgb 1.5s steps(1) infinite;
animation: rgb 1.5s steps(1) infinite;
}
效果就變成了每 0.5 秒切換一次背景色,沒有漸變過渡
具體應用:兩種狀態無限切換(閃爍)
.blink {
-webkit-animation: blink 1s steps(1) infinite;
animation: blink 1s steps(1) infinite;
}
@keyframes blink {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
}
2.添加關鍵影格去掉平滑過渡
閃爍效果有另一種有趣的實現方式:
.blink {
-webkit-animation: blink 1s linear infinite;
animation: blink 1s linear infinite;
}
@keyframes blink {
0% {
opacity: 0;
}
50% {
opacity: 0;
}
50.01% {
opacity: 1;
}
100% {
opacity: 1;
}
}
雖然還是 linear 平滑過渡,但插入的:
50.01% {
opacity: 1;
}
去掉了 50% -> 100% 的補間,把透明度補間轉移到 50% -> 50.01%,時間較短的情況下,這個補間變化不會被察覺,當然,如果時間足夠長,比如:
.blink {
-webkit-animation: blink 10000s linear infinite;
animation: blink 10000s linear infinite;
}
就應該能看到透明度在某 1 秒內從 0 漸變到 1,但一般情況下,這樣實現閃爍在效果上是沒有問題的
3.關鍵影格控制延遲
animation-delay 只在動畫開始前有效,每次重複不會插入延遲。類似於上面 50.01% 的技巧,可以透過插入空白關鍵影格來給每次重複插入延遲,實現 loading 轉一圈等一等的效果:
.wait {
-webkit-animation: wait 1s linear infinite;
animation: wait 1s linear infinite;
}
@keyframes wait {
0% {
-webkit-transform: rotateZ(0);
transform: rotateZ(0);
}
40% {
-webkit-transform: rotateZ(0);
transform: rotateZ(0);
}
100% {
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
}
做到了每轉一圈等 0.4s
4.steps 逐影格動畫
把序列影格平鋪在一張圖片上,修改 background-position
用 steps() 實現的話需要在末尾複製第一影格(比如 6 影格動畫,需要 7 影格平鋪圖),例如:
.walk {
background: url(walk.svg);
width: 162px;
height: 230px;
-webkit-animation: walk 1s steps(22) infinite;
animation: walk 1s steps(22) infinite;
}
@keyframes walk {
0% {
background-position: 0 0;
}
100% {
background-position: -3564px 0;
}
}
其中 walk.svg 橫向鋪滿了 23 影格,每影格尺寸是 162 * 230,向左抽背景圖片,最多能抽 162 * 22 = 3564,此時顯示最後一影格(圖片影格內容與第一影格相同),首尾接起來
當然,還有另一種方法,用 steps(1) 去掉平滑過渡,然後手動設置 22 個關鍵影格,比較費勁,這裡不給例子,但肯定是可行的
線上 Demo:http://www.ayqy.net/temp/animation/css-animation-tricks.html
六.總結
CSS animation 的定義方式和 Flash 非常相似,比如 Flash 中的幾個概念:
-
關鍵影格:如果你希望某處的內容要跟前面不一樣,就插入關鍵影格
-
空白關鍵影格:表示上面沒內容,以小白點顯示。他可以跟關鍵影格互相轉換,放了內容就成關鍵影格了。關鍵影格上的內容去掉就是空白關鍵影格
-
普通影格:關鍵影格或者空白關鍵影格後面延續的是普通影格。普通影格是延續之前關鍵影格的內容,所以他的作用可以用來控制動畫的顯示時間
對應到 CSS 的 @keyframes 定義中感受一下,是不是有點意思?
暫無評論,快來發表你的看法吧