用視頻軟件AE + bodymovin製做網頁動畫

咱們知道,作動畫有多種形式,能夠用CSS的animation,也能夠用Canvas,或者是用JS控制CSS的屬性造成動畫。咱們常用CSS作一些比較簡單的動畫,像過分、加載的動畫,對於一些比較複雜的,可能會作成gif,或者是用Canvas,使用Canvas的控制粒度能夠很細,同時工做量相對也比較大。作動畫還有其它的方式,那就是使用After Effect(AE)/ Flash/Premiere(Pr)/會聲會影等視頻軟件,這種可視化的製做方式相對於直接寫代碼來講,會更容易簡單天然。作動畫自己應該使用工具進行製做,可是這種視頻軟件作出來的動畫最後都是生成視頻文件,而且一般體積還很大,沒有辦法直接移植到網頁上去。
javascript

然而好消息是,如今咱們可使用AE作動畫,而後使用bodymovin插件導出成html文件進行播放。AE是Adobe推出的一個很出名的視頻後期處理軟件,有些電影就是用AE作的,如變形金剛,還有人把AE當成增強版PS使用。也就是說假如咱們能夠AE作出一些電影級別的效果,而後用html播放,那是一件多麼酷炫的事情。css

1. 安裝bodymovin

bodymovin是一個AE的一個開源的第三方擴展,github地址。上面能夠下載這個插件。而後再安裝一個ZXPInstaller來安裝這個文件,而後重啓AE就能夠了,固然前提是你要安裝一個AE。它支持AE CC版本:html

After Effects CC 2017, CC 2015.3, CC 2015, CC 2014

安裝完以後,點擊AE的菜單Window -> Extensions -> Bodymovin就會彈出一個窗口:java

2. 使用AE製做動畫

我相信不少人都沒有玩過AE,因此這裏我簡單地介紹一下。首先新建一個工程(project),而後新建一個合成(composition),選擇1080p/29fps,時長爲10s,它就會建立一個10s的合成。以下時間軸面板的顯示:node

這個時間軸將會是頻繁操做的地方。點擊文字工具,在上方的預覽窗口選中一個位置點擊建立文字,而後把它拖到窗口外面,由於咱們準備作一個文字從外面進來的動畫,因此剛開始它是在外面的。把上圖右邊的藍色豎線表示的時間線拖到0s的位置,而後在左邊的文字圖層的Position屬性打一個關鍵幀,以下圖所示:git

而後把時間線挪到3s的位置,改變文字的Position,把它挪到窗口的中間,這個時候AE會自動在時間線的位置打一個關鍵幀,以下圖所示:github

而後按一下空格鍵進行預覽,預覽窗口就會播放起了咱們剛剛設定的動畫:npm

你會發現,這個過程不是和CSS的keyframe動畫同樣的麼?沒錯!動畫的原理都是同樣,經過設定關鍵幀製做動畫。如今來比較一下用AE和用CSS/Canvas作這個動畫的區別。json

3. 關鍵幀動畫

如今用CSS作這個動畫,以下代碼所示:canvas

<style> .text{ animation: move 3s linear infinite; } @keyframes move{ from{ transform: translateX(-320px); } to{ transform: translateX(100px); } } </style> <div class="container"> <p class="text">Hello, frontend</p> </div>複製代碼

咱們給animation添加一個動畫,這個動畫有兩個關鍵幀,分別在0%和100%的位置,須要變化的是transform的屬性。這段代碼在瀏覽器運行,就會有剛剛用AE作的動畫的效果了。若是用Canvas呢,應該怎麼實現呢?

以下代碼所示:

<canvas id="text-move" width="600" height="400"></canvas> <script> !function(){ window.requestAnimationFrame(draw); var canvas = document.querySelector("#text-move"), ctx = canvas.getContext("2d"); function draw(){ //計算文字position var textPosition = getPosition(); drawText(); window.requestAnimationFrame(draw); } }();複製代碼

這個是canvas動畫的基本框架,先註冊requestAnimationFrame的draw函數,使得瀏覽器在從新繪製屏幕時會先調一下這個函數,理想狀況下1s會繪製60幅圖片,也就是說1s爲60幀/60fps。

上面代碼最關鍵的地方是在於計算文字位置position,一樣地,也是要先設定初始位置和終點位置還有動畫時間,從而知道移動的速度v,即每1s多少距離,記錄一個動畫開始時間,而後在每次draw的時候用Date.now()獲取當前時間減掉開始時間,就獲得時間t,而後用v * t就能夠獲得位移。這就是用Cavans作動畫的基本原理,咱們看到,用Canvas須要本身實現一個關鍵幀系統。

從抽象級別來看的話,AE > CSS >> Canvas,使用AE我只須要拖一拖,而後打上幾個關鍵幀,而使用CSS,我須要把個人操做寫成代碼,而使用Canvas我須要從0開始一點一點去控制,固然你可使用一些動畫和遊戲的引擎提升效率。因此若是有一個可視化界面讓你去完成一些複雜的操做,和讓你一行一行去寫代碼的方式選擇的話,我想大部分人應該會選擇前者。固然這二者的區別不只僅是操做上的簡便性,使用AE借用插件還能夠快速地製做出一些複雜的效果。

4. bodymovin小試牛刀

剛剛已經用AE作了一個最簡單的動畫,如今用bodywin把它導出來。打開bodymovin,選中合層,選擇輸出路徑,以下圖所示:

而後點擊Render,完成它會輸出一個json文件,打開這個導出的文件:

{"v":"4.10.1","fr":29.9700012207031,"ip":0,"op":95.0000038694293,"w":1920,"h":1080,"nm":"Comp 1","ddd":0,"assets":[],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"Myriad Pro","fWeight":"","fStyle":"Regular","fName":"MyriadPro-Regular","ascent":70.9991455078125}]},"layers":[{"ddd":0,"ind":1,"ty":5,"nm":"hello, frontend","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-1017,692,0],"e":[458,692,0],"to":[245.83332824707,0,0],"ti":[-245.83332824707,0,0]},{"t":90.0000036657751}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":164,"f":"MyriadPro-Regular","t":"hello, frontend","j":0,"tr":0,"lh":196.8,"ls":0,"fc":[0,0.64,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":300.00001221925,"st":0,"bm":0}]}

這個文件記錄了全部動畫的過程,如上加粗字體是咱們剛剛打的兩個關鍵幀的位置。而後安裝一下bodymovin的引擎,可在github上面下載bodymovin.js或者是npm install一下:

npm install bodymovin複製代碼

而後就可使用bodymovin了,以下html:

<!DOCType html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="animation-container" style="width:100%"></div> <script src="node_modules/bodymovin/build/player/bodymovin.js"></script> <script src="index.js"></script> </body> </html>複製代碼

index.js以下代碼所示:

var animation = bodymovin.loadAnimation({
    container: document.getElementById('animation-container'),
    renderer: 'canvas', //svg、html
    loop: true,
    autoplay: true,
    path: 'data.json'
})複製代碼

調用它的loadAnimation的API,傳幾個參數,它支持canvas/svg/html三種形式,也就是說它能夠用canvas作動畫,也能夠用svg和html,其中canvas的性能最高,可是canvas有不少效果不支持。data.json的位置經過path告訴它。全部的動畫就經過改變path指向的data.json文件區分,而其它的參數不用變。也就是說全部的動畫內容和效果都是經過data.json控制的。

如今在瀏覽器上面運行一下,你會發現報了一個錯:

後來發現這個錯誤是由於文字的緣由,若是是用canvas的方式的時候要把文字導成svg的形式,而不是一個純文本而後經過設置font-family,這個能夠在bodymovin裏面進行設置,以下圖所示:

還能夠直接導出一個完整的demo,直接打開html就能夠運行,這個比較方便。效果以下:

而且咱們發現,它的大小和位移都是相對於容器的,當你把窗口拉小,它也會跟着變小。當使用svg的時候,它是用JS控制svg path標籤的transform:

當使用html時,它是控制CSS的transform:

咱們一個hello, world的工程已經能夠跑起來,bodymovin能支持多複雜的動畫呢?

5. AE的攝像機

用AE作動畫的時候常常會用到AE的攝像機圖層,所謂攝像機就是一個視角,默認狀況下這臺攝像機是從正前方中間拍過去的,咱們能夠改變這臺攝像機的位置,如把攝像機往前推那麼內容就會放大,把攝像機往左右移動,那麼看到的內容就會發生傾斜,它有不少仿攝像機的參數能夠控制:

攝像機屬性均可以經過打關鍵幀作動畫,如今咱們加上攝像機作3d的動畫。作完後,若是還用canvas的話,它會提示你不能使用canvas,由於它目測不支持WebGL轉換,以下圖所示:

提示說使用了一個3d camera,嘗試使用html renderer,這裏要改爲html。最後的效果以下:

經過檢查,能夠看到攝像機也是用transform的matrix控制的。完整的dmo可見這個連接

而後咱們再繼續作複雜的動畫

6. 複雜動畫

在全部特效裏面,筆者最喜歡的是粒子效果,這種效果也是電影裏面常常用到的特效,如冰雪女王的冰雪魔法:

還有文字的粒子效果:

可是這種效果我試了一下沒有辦法導出來,這種效果自己就比較複雜,渲染起來比較耗時,在html實時播放也不太現實。

還有有時候會報一些奇怪的錯誤,最常報的一個錯誤是這個:

bodymovin.js:9249 Uncaught TypeError: this.addTo3dContainer is not a function

多是使用了一些特定效果,觸發了它的bug。

可是不要沮喪,咱們仍是能夠導出一些複雜的效果的,作動畫這種關鍵仍是在於idea。

例如能夠作一個裝飾的小動畫,以下所示:

一個完整的demo見這個網址

還能夠作一個相冊視頻,效果以下:

完整的demo見這個網址

若是是作成一個1080p的視頻,1.5分鐘的mp4格式就算壓得比較厲害也要100多MB,可是如今我只要加載一個90kb的json文件和一個240kB的庫文件以及10Mb左右的圖片就能夠了。而且裏面的文字和圖形仍是矢量的。

如今來看一下CPU消耗,能夠看到這個相冊視頻svg動畫仍是很耗CPU的,可是你開一個視頻播放器也一樣挺消耗CPU資源的。


無論怎麼樣,bodymovin提供了另一種作網頁動畫的全新方式,擺脫那種純代碼控制的黑暗,甚至你都不用學Canvas和WebGL,也能夠作出很酷炫的動畫。可是無疑這種方式存在一種弊端,那就是沒辦法添加參數控制,例如我作一個憤怒的小鳥,我得經過拉弓的方向和力度以及小鳥的重量去計算它的軌跡。可是用AE作的只能是純動畫。因此平時能夠二者結合。

bodymovin還支持轉成IOS/Android代碼,我感受這個東西發展還在初級階段,網上也沒有不少關於這個的介紹。可是隨着這個的承認度提高,發展愈來愈好,說不定之後可以支持更多的特效,甚至能夠提供參數支持。

相關文章
相關標籤/搜索