動畫調研-V1
前言:動畫從用途上可以分為兩種,一種是展示型的動畫,類似於一張GIF圖,或者一段視訊,另一種就是互動性的動畫。這兩種都有具體的應用場景,比如在我們資訊流業務中,從下拉頁面到進入活動頁這個過程中,我們完全可以用一個展示型的入場動畫代替原本可能只有一個小圓圈的的loading頁。
展示型動畫:
互動性動畫(可以看到螢幕那個小手勢):
一. 展示型動畫 VS 互動性動畫
展示型動畫在實際使用的場景中,實現的方法很多,比如用gif圖
,canvas
,css3
動畫等,但是最終輸出的結果是不帶有互動的,也就是從動畫起始狀態到結束狀態一氣呵成,這個過程使用者可以感知,但是無法參與。對於互動性動畫而言,我們可以在動畫播放的某個時間節點觸發相應的操作,進而讓使用者參與到其中,最常見的例子比如紅包雨,或者是我們世界盃踢足球的動畫,不僅僅能提升使用者的體驗,還能提升我們的產品的多元性。然而互動性動畫經常面臨的一個問題就是,通過原生程式碼實現互動動畫是很複雜的,同時效能和相容性是不得不認真考慮的問題,比較好的解決方案還是尋求相關的框架。
二. 動畫使用到的技術
- CSS3 Animation
- canvas
- SVG
- WebGL
- 利用JavaScript驅動的動畫
伴隨著CSS3的發展,利用CSS3的transform
和動畫的@keyframes
就可以完成很多酷炫的動畫,但是CSS3的動畫應用場景僅僅是展示型動畫,只要動畫開始,我們就無法控制動畫的狀態,而且對於複雜的動畫,CSS3就顯得很無力了。對於JavaScript驅動的動畫,在一定程度上就可以彌補這些缺點,比如anime.js
增加的timeline
的概念,通過將各部分動畫鏈式執行,從而完成更為複雜的動畫,同時動畫執行的各個階段提供的回撥函式也能讓我們更方便的控制動畫執行的狀態,為互動提供了可能。對於canvas
,在 canvas
上繪製的圖形自身不支援 DOM 事件
,只有canvas
標籤自身支援 DOM 事件監聽。因此需要對 canvas 容器
的事件進行處理,實現相對應事件的監聽及處理。WebGL
可以為canvas
提供硬體GPU
加速渲染,藉助使用系統GPU可以在移動端中更流暢的展示動畫.
三. 相關技術的相容性
- 對於
CSS3的animation
,相容性如下:
canvas
相容性如下:
WebGL
相容性如下:
可以看到,CSS3的animation和canvas支援性比較好,只有WebGL在Android 4.4 Browser 完全不支援,後續我們會提到PixiJs庫,可以採用WebGL渲染,也可以優雅降級採用canvas渲染
四. 現有的幾種方案
1. AE + bodymovin + Lottie
適用場景:主要還是展示型動畫
簡介:通過
AE 上的 Bodymovin 外掛
將 AE 中製作好的動畫匯出成一個 json 檔案,通過Lottie
對JSON
進行解析,最後以SVG/canvas/html
的方式渲染動畫。
官方文件:airbnb.io/lottie/
codepen倉庫:codepen.io/collection/…
優點:
- 跨平臺,一次繪製、一次轉換、隨處可用
- 檔案更小,獲取AE匯出的
JSON
,最後通過lottie
渲染為canvas/svg/html格式
- 可以通過api操縱動畫的一些屬性,比如動畫速度;新增動畫各個狀態的回撥函式
- 動畫都是在
After Effects
中建立的,使用Bodymovin
匯出,並且本機渲染無需額外的工程工作。 - 解放前端工程師的生產力,提高設計師做動效的自由度
缺點:
Bodymovin
外掛待完善,仍然有部分 AE 效果無法成功匯出- 對於互動方面支援的還不是很好,更多的是用來展示動畫
Lottie
對json
檔案的支援待完善,目前有部分能成功匯出成json
檔案的效果在移動端上無法很好的展現- 很多AE的效果是不支援的 檢視支援的特性:Supported Features
2. Anime.js
適用場景: 強展示+弱互動性動畫
簡介:Anime.js是一個輕量級的js驅動的動畫庫,主要的功能有
– 支援keyframes,連線多個動畫
– 支援Timeline,為實現更為複雜的動畫提供了可能
– 支援動畫狀態的控制playback control,播放,暫停,重新啟動,搜尋動畫或時間線。
– 支援動畫狀態的callback,在動畫開始,執行中,結束時提供回撥函式
– 支援svg動畫
– 可以自定義貝塞爾曲線
– 任何包含數值的DOM屬性都可以設定動畫
GitHub:github.com/juliangarni…
codepen倉庫:codepen.io/collection/…
文件演示:animejs.com/documentati…
功能介紹:
-
一定程度上,
anime.js
也是一個CSS3動畫庫
,適用所有的CSS屬性
,並且實現的@keyframes
能更方便的實現幀動畫,替代CSS3複雜的定義方式。使用物件陣列的形式定義每一幀
戳我:keyframes例項anime({ targets: `div`, translateX: [ { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一幀 { value: 0, duration: 1000, delay: 500, elasticity: 0 } //第二幀 ] }) //這個例子實現了目標元素在兩幀中實現水平位移 複製程式碼
-
提供的
Timeline
能實現更為複雜的動畫效果,通過這個Timeline
,我們可以維護不同的動畫之間的關係,進而通過多個不同的動畫組成一個更為複雜的動畫。
戳我:Timeline例項var myTimeline = anime.timeline(); //通過.add()方法新增動畫 myTimeline .add({ targets: `.square`, translateX: 250 }) .add({ targets: `.circle`, translateX: 250 }) .add({ targets: `.triangle`, translateX: 250 }); 複製程式碼
-
動畫播放的控制,常見的有暫停,重播,繼續,動畫狀態的跟蹤,自動播放,迴圈次數,抖動效果
戳我:playback controls例項 -
為動畫提供了回撥函式,在動畫或時間線完成的開始,期間或之時執行回撥函式。
戳我:callback例項var myAnimation = anime({ targets: `#begin .el`, translateX: 250, delay: 1000, begin: function(anim) { // callback console.log(anim.began); // true after 1000ms } }); 複製程式碼
-
支援
promise
,動畫結束後,呼叫anime.finishe
d會返回一個promise物件
。
戳我:promise例項 -
支援
svg
繪製路徑,目前不支援canvas繪製
戳我:SVG例項 -
對於
input
這樣帶有數值的元素標籤,也可以通過anime例項
來設定動畫
戳我:DOM ATTRIBUTES例項anime({ targets: input, value: 1000, // Animate the input value to 1000 round: 1 // Remove decimals by rounding the value }); 複製程式碼
優點:
- 顯而易見,
anime.js
不僅實現了CSS3動畫
的深度封裝,更多的是通過js驅動來實現操作動畫的狀態,timeline
實現了對於多個分支動畫的管理,對於實現更為複雜的動畫提供了可能 - 通過
anime.js
提供的playback controls
和callback
,同時對於promise
的支援,讓我們對於動畫的簡單互動有了操作的空間 - 雖然不支援
canvas
,但是支援svg繪製路徑
,我對svg還不是很瞭解,待之後深入學習後,在做一個補充。 - 瀏覽器相容性比較好,
Android 4
以上全部支援
缺點與不足:
anime.js
做展示型動畫是可以勝任的,在做互動性動畫方面還是需要看場景,它更多適合做一些小型的互動動畫,類似於通過觸控螢幕踢足球這種強互動的,anime.js
就不是很有優勢了。
3. PixiJs
適用場景:互動性動畫,動畫小遊戲
簡介:PixiJS是一個2D 渲染引擎, Pixi 主要負責渲染畫面。可以建立豐富的互動式圖形,動畫和遊戲,而無需深入瞭解WebGL API或處理瀏覽器和裝置相容性的問題。與此同時,PixiJS具有完整的WebGL支援,如果需要,可以無縫地回退到HTML5的canvas。PixiJs預設使用WebGL渲染,也可以通過宣告指定canvas渲染,WebGL在移動端Android 4.4 browser並不支援,不過可以使用canvas優雅降級。
Github: github.com/pixijs/pixi…
官方文件: pixijs.download/release/doc…
官方網站:www.pixijs.com/
Examples:pixijs.io/examples/#/…
特性(摘自官方DOCS):
- 支援
WebGL渲染
- 支援
canvas 渲染
(官方稱PixiJS在canvas渲染方面現在是最快的) - 非常簡單易用的
API
- 豐富的互動事件,比如完整的滑鼠和移動端的觸控事件
Pixi
使用和Canvas Drawing
幾乎一致的 api,但不同於Canvas
的繪畫 api,使用 Pixi 繪製的圖形是通過WebGL
在GPU
上渲染- 還有一系列特性需要在學習PixiJs之後瞭解
優勢:
- 最大優勢莫過於通過
WebGL
來呼叫GPU渲染動畫,這樣極大的提升了效能 - 無需深入瞭解
WebGL API
或者是瀏覽器相容性
(因為下面這條原因) - 支援
canvas
回退,當前裝置不支援WebGL
時,PixiJs
會使用canvas渲染
動畫 - 完整的
DOCS
,比較活躍的社群,有利於深入的學習。不過我感覺PixiJs學習成本相對來說還是很高的
缺點:
- 首先是相容的問題,WebGL在
Android 4.4
是不支援的,只能使用canvas進行降級 - Pixi 主要負責渲染畫面,很多其它功能開發者得自己寫或搭配其它庫來使用,不過按照目前來看,是滿足我們的需求的。
效能:
- 對於手機版本
Android4.4
以上的手機,除了程式碼層面造成的效能不足,通過WebGL呼叫GPU渲染,效能還是有保障的。然而對於Android4.4只能使用canvas渲染,效能還是要看動畫的複雜度,以及程式碼的優化
五. 總結
針對不同的動畫需求,我總結了三種不同場景下的動畫庫。對於展示性的動畫,我們完全可以使用第一種方案,讓設計同學提供動畫,我們利用動畫匯出的JSON
,將動畫還原為svg/canvas/html
。如果場景是互動型或者需要做一個小遊戲,可以採用第三種方案PixiJs
,通過WebGL
來渲染,利用硬體資源,極大的提升效能,在相容性方面,對於不支援WebGL
的瀏覽器,可以使用canvas渲染
來平穩回退
。最後一種場景就是弱互動強展示,這種場景往往就是使用者點選一下暫停執行相應操作,待操作完成繼續播放動畫,互動方面比較偏弱
,這種場景下可以採用第二種方案 Anime.js
,Anime.js不僅僅支援所有的css 屬性,而且可以通過Timeline,callback, playback controls來控制動畫執行的各個狀態。而且相容性滿足我們的需求,在效能方面,只要不過多的造成頁面迴流
,多使用transform操作複合層,效能還是可以的(待多多嘗試,就我看的幾個例子效能還是不錯的)。最後,從需求角度分析之後,從學習成本做個簡單的小排名:PixiJs > Anime.js > lottie
六.動畫效能分析參考
- 實現達到 60FPS 的高效能互動動畫
- requestAnimationFrame 效能更好
- 使用瀏覽器開發者工具檢測 CSS 動畫效能【工具】
- 使用 CSS3 實現 60FPS 動畫
- CSS 動畫之硬體加速
- Web 動畫效能指南