CSS 動畫

CSS 中的 transformtransitionanimation 是分開的三部份內容,其中 transfrom 主要是控制元素變形,並無一個時間控制的概念,而 transitionanimation 纔是動畫的部分,它們能夠控制在一個時間段裏,元素在兩個或以上的狀態切換的效果。css

基本上咱們會有這樣的一個簡單的概念,CSS 的動畫效果由瀏覽器控制和渲染,理論上比 JavaScript 的動畫效果性能好,可是控制上沒有 JavaScript 那麼靈活方便。html

迪士尼出版的一本書中說起了動畫效果的十二個原則,這篇文章講解得比較詳細,而且將其結合到頁面動畫中:網頁動畫的十二原則css3

transition

transition 容許咱們在 CSS 屬性變化時給它添加一個過分的動畫效果。一般狀況下,CSS 屬性變化是當即生效的,新的屬性值在超級短的時間內替換掉舊的屬性值,而後瀏覽器從新繪製樣式內容(多是 reflow 或者 repaint)。大部分狀況下會感受樣式變化突兀,而 transition 則能夠添加順滑的一個變化效果。例如:git

.content {
  background: magenta;
  transition: background 200ms ease-in 50ms;
}

.content:hover {
  background: yellow;
  transition: background 200ms ease-out 50ms;
}

transition 的兼容性,不算差,基本上移動設備均可以使用了,而且能作到漸進加強,支持的便有過渡效果,不支持的即是直接切換,因此能夠放心使用。github

transition 屬性

CSS 的 transition 有四個屬性:web

  • transition-delay 延遲多久後開始動畫算法

  • transition-duration 過渡動畫的一個持續時間chrome

  • transition-property 執行動畫對應的屬性,例如 colorbackground 等,可使用 all 來指定全部的屬性瀏覽器

  • transition-timing-function 隨着時間推動,動畫變化軌跡的計算方式,常見的有:linear,ease,ease-in,ease-out,cubic-bezier(...) 等。詳細參考:transition-timing-function,裏邊有各個效果的簡單例子。網絡

這四個屬性能夠簡寫成爲:

.class {
  transition: <property> <duration> <timing-function> <delay>  
}

例如前邊的那個例子,當 .content 元素 hover 時,50 毫秒後背景顏色從 magenta 漸變到 yellow,持續時間 200 毫秒,使用的是 ease-out 的算法。留意下:transition 生效的是對應的選擇器的屬性,例如 .content:hover 中的 transition 即是從 .content 的 magenta 到 yellow 過渡效果的控制,而 .content 中的 transition 則是控制不 hover 時,背景顏色從 yellow 到 magenta 的變化過程。

all 這個屬性值是這樣的,它對應選擇器下的元素的全部 CSS 屬性生效,不管在哪裏聲明的 CSS 規則,並不侷限於在同個代碼塊下。

若是須要不一樣屬性對應不一樣的效果,能夠這麼來寫:

.demo {
  transition-property: all, border-radius, opacity;
  transition-duration: 1s, 2s, 3s;
  /* 當這樣使用時,確保 all 在第一個,由於若是 all 在後邊的話,它的規則會覆蓋掉前邊的屬性 */
}

transitionnone 屬性較少用到,通常用於移除本來有的動畫效果。none 無法和逗號一塊兒使用來移除特定屬性的動畫效果,只能直接幹掉 transition,若是要移除特定的屬性效果,能夠重寫 transition 而不把要移除的屬性寫進去,或者比較 trick 的作法是設置 duration 爲 0。

並非全部的 CSS 屬性都是能夠添加 transition 效果的。詳細能夠參考文檔:animatable properties。可能常常遇到的就是 display 這個屬性並不能添加 transition 效果,你能夠考慮使用 visibility 或者後邊會說起的 animation

關於 transition-timing-function 的各個算法的一個變化曲線是怎麼樣的,咱們可使用 chrome 的開發者工具來看一下,CSS 中你編寫了對應的 transition 後,把鼠標移到 transition-timing-function 的那個值前邊,以下圖:

Timing function

這樣你即可以很清晰地看到這個算法的一個變化軌跡是怎麼用的,而後選擇符合本身須要的一個算法。

transition 相關的事件

transitionend 事件會在 transition 動畫結束的時候觸發。一般咱們會在動畫結束後執行一些方法,例如繼續下一個動畫效果或者其餘。Zepto.js 中的動畫方法都是使用 CSS 動畫屬性來處理,而其中動畫運行後的回調便應該是使用這個事件來處理。

transitionend 事件觸發時會傳入一些動畫相關的參數,例如:propertyNameelapsedTime,詳細內容能夠參考:transitionend

transition 應用

transition 在不少 UI 框架中是很常見的屬性,當咱們開發一個交互效果的時候,從某個狀態到達另一個狀態時,transition 可使得這個過程變得更加溫馨和順滑。例如上邊的 hover 時的背景顏色的切換,控制元素的顯示和隱藏時使用 opacity 來實現漸隱漸現。

transition 配合上 transform 提供的多樣化的元素變化能力後,即可以繪製出不少有趣的交互漸變效果了。最近使用過程當中作的一個簡單效果的例子,點擊查看

很常見還有表單 input 報錯時邊框變紅,按鈕 hover 時背景漸變等,不少的 CSS 交互效果會由於 transition 變得更加天然。

animation

雖然 transition 已經提供了很棒的動畫效果了,可是咱們只可以控制從一個狀態到達另一個狀態,無法來控制多個狀態的不斷變化,而 animation 而幫助咱們實現了這一點。使用 animation 的前提是咱們須要先使用 @keyframes 來定義一個動畫效果,@keyframes 定義的規則能夠用來控制動畫過程當中的各個狀態的狀況,語法大抵是這個樣子:

@keyframes W {
  from { left: 0; top: 0; }
  to { left: 100%; top: 100%; }
}

@keyframes 關鍵詞後跟動畫的名字,而後是一個塊,塊中有動畫進度的各個選擇器,選擇器後的塊則依舊是咱們常見的各個 CSS 樣式屬性。

在這裏,控制動畫的整個過程的選擇器很重要,語法相對簡單,你可使用 from 或者 0% 來表示起始狀態,而 to100% 來表示結束狀態。中間的部分你均可以使用百分比來進行表示。選擇器後的塊則是在到達這個進度狀態時元素的樣式應該是怎麼樣的,整個的過渡動畫在這個的控制基礎上由瀏覽器去繪製。

一樣地,不是全部的屬性均可以有動畫效果,MDN 維護了一份 CSS 動畫的屬性列表 可供參考。

一般來講,多個狀態下的相同屬性的值應該是能夠取到它們的中間值的,例如 left 從 0% 到 100%,若是無法取到中間值,如 height 從 auto 到 100px,有可能出現奇怪的一些情況,而且不一樣瀏覽器對此的處理也不盡相同,因此請儘可能避免這種狀況。

animation 屬性

animation 的屬性比 transition 多,以下:

  • animation-name 你須要的動畫效果的 @keyframes 的名字。

  • animation-delaytransition-delay 同樣,動畫延遲的時間。

  • animtaion-durationtransition-duration 同樣,動畫持續的時間。

  • animation-direction 動畫的一個方向控制。
    默認是 normal,若是是上述的 left 從 0% 到 100%,那麼默認是從左到右。若是這個值是 reverse,那麼即是從右到左。

因爲 animation 提供了循環的控制,因此還有兩個值是 alternatealternate-reverse,這兩個值會在每次循環開始的時候調轉動畫方向,只不過是起始的方向不一樣。

例如仍是 left 的例子,假設設置了 animation-direction: alternate; animation-iteration-count: infinite;,那麼這個元素從左到右移動後,便調轉方向,從右到左,如此循環。

  • animation-fill-mode 這個屬性用來控制動畫先後,@keyframes 中提供的 CSS 屬性如何應用到元素上。
    默認值是 none,還有其餘三個選擇:forwardsbackwardsboth

假設是 none,那麼動畫先後,動畫中聲明的 CSS 屬性都不會應用到元素上。即動畫效果執行後,元素便恢復正常狀態。

若是是 forwards,那麼動畫結束後,會把最後狀態的 CSS 屬性應用到元素上,即保持動畫最後的樣子。而 backwards 則相反,both 則都會,計算得出最後的一個結果。

  • animation-timing-functiontransition-timing-function 同樣,動畫變化軌跡的算法。

  • animation-iteration-count 動畫循環次數,若是是 infinite 則無限次。有趣的是,支持小數,即 0.5 表示動畫執行到一半。

  • animation-play-state 動畫執行的狀態,兩個值 running 或者 paused,能夠用來控制動畫是否執行。

上述這些屬性能夠簡寫爲:

.class {
  animation: <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode> <play-state> <name>
}

略長,固然,平時使用中多是省略部分參數的。

animation 須要留意的東西

優先級

記得 CSS 中的層疊概念麼,優先級高的屬性會覆蓋優先級低的屬性,當 animation 應用到元素中時,動畫運行過程當中,@keyframes 聲明的 CSS 屬性優先級最高,比行內聲明 !important 的樣式還要高。如今瀏覽器的實現是這樣子的,可是標準文檔中的說法應該是能夠被 !important 聲明的屬性所覆蓋。

多個動畫的順序

因爲 animation-name 是能夠指定多個動畫效果的,因此這裏便會出現動畫的一個順序問題。後指定的動畫會覆蓋掉前邊的,例如:

#colors {
  animation-name: red, green, blue; /* 假設這些 keyframe 都是修改 color 這個屬性 */
  animation-duration: 5s, 4s, 3s;
}

上述代碼的動畫效果會是這樣:前 3 秒是 blue,而後接着 1 秒是 green,最後 1 秒是 red。整個覆蓋的規則是比較簡單的。

display 的影響

若是一個元素的 display 設置爲 none,那麼在它或者它的子元素上的動畫效果便會中止,而從新設置 display 爲可見後,動畫效果會從新重頭開始執行。

animation 相關事件

咱們能夠經過綁定事件來監聽 animation 的幾個狀態,這些事件分別是:

  • animationstart 動畫開始事件,若是有 delay 屬性的話,那麼等到動畫真正開始再觸發,若是是沒有 delay,那麼當動畫效果應用到元素時,這個事件會被觸發。

  • animationend 動畫結束的事件,和 transitionend 相似。若是有多個動畫,那麼這個事件會觸發屢次,像上邊的例子,這個事件會觸發三次。若是 animation-iteration-count 設置爲 infinite,那麼這個事件則不會被觸發。

  • animationiteration 動畫循環一個生命週期結束的事件,和上一個事件不同的是,這個在每次循環結束一段動畫時會觸發,而不是整個動畫結束時觸發。無限循環時,除非 duration 爲 0,不然這個事件會無限觸發。

animation event 相關的屬性能夠參考:animationEvent

animation 應用

animation 能夠實現控制在多個狀態下進行動畫切換,因此應用的場景比 transition 要普遍得多,可使用 animation 實現大量的動效,具體能夠查看下 animate.css 這個庫。

我上邊提到的 簡單例子 中也包括了一個簡單地使用 animation 來縮放字體,和一個簡單進度條的例子。

CSS 動畫的性能

如今愈來愈多的頁面開發是面向移動端,因此咱們會更加關注性能方面的問題。瀏覽器繪製動畫的過程當中,涉及的主要是 Layout,Paint,Composite 的處理,當一個動畫觸發的瀏覽器處理越少,影響的區域越少,那麼便消耗越低,性能上越好。

咱們能夠參考這個 CSS Triggers 網站提供的列表,這裏展現了修改屬性時對應的瀏覽器內核所須要作的處理。簡單歸納來講,動畫儘可能少涉及佈局相關的調整,由於佈局上一旦變化,會涉及外部元素和內部元素的位置調整,對瀏覽器的消耗至關大,而在現代瀏覽器中,擁有比較好動畫性能的屬性就是 transformopacity,建議須要動畫的時候多往這兩個屬性考慮,例如字體要放大,避免使用 font-size,而是用 transform: scale() 等。

咱們可使用 will-change 來聲明即將變化的屬性,這可讓瀏覽器提早作一些優化工做,關於這個屬性,更多內容能夠參考: will-change。值得留意的是,別濫用 will-change,在太多的元素上使用或者應用太多的屬性都會致使瀏覽器資源浪費。

Chrome 瀏覽器的開發者工具提供的 Timeline 工具能夠幫助咱們來查看頁面渲染的一個性能表現狀況,以下圖:

Chrome Timeline

Timeline 能夠用來獲取腳本執行性能,網絡請求性能等的表現數據,可是這裏咱們只是關於動畫渲染,因此只是勾選了 paint。咱們能夠看到渲染能夠保持在 60 FPS,便不會感受到卡頓。當渲染 FPS 太低的時候,圖示那裏會出現紅色的提示,經過這個工具能夠幫助咱們在須要的時候作針對性的優化。

對於 CSS 動畫性能上的東西,本人還比較缺少實踐經驗,最近 w3cplus 上出現了大量的關於 CSS 動畫性能相關的文章,有興趣能夠查閱。

相關文章
相關標籤/搜索