作者:vivo 網際網路前端團隊- ZhaoJie
本文將從各個角度來對動畫整個體系進行分類,並且介紹各種前端動畫的實現方法,最後我們將總結在實際開發中的各個場景的動畫選擇方案。
前端動畫場景需求多
對眾多動畫場景的技術實現方案選擇上比較模糊
各動畫方案的優劣及適用場景認識模糊
現有動畫庫太多,不知道選哪個
主流動畫庫的適用場景認識模糊
下面首先讓我們從各個角度來對動畫整個體系進行分類,讓我們清晰的瞭解動畫整個體系。
首先我們從動畫的用途或者說是業務的角度來進行區分,將我們平時的動畫分為展示型動畫和互動型動畫。
類似於一張GIF圖,或者一段視訊。比如在開啟寶箱的時候,我們會加入一個切場過渡動畫,來替代原有的生硬等待結果。
展示型動畫在實際使用的場景中,實現的方法很多,比如用GIF圖,canvas,CSS3動畫等,但是最終輸出的結果是不帶有互動的,也就是從動畫起始狀態到結束狀態一氣呵成,這個過程使用者可以感知,但是無法參與。
使用者自已參與的,對於互動性動畫而言,我們可以在動畫播放的某個時間節點觸發相應的操作,進而讓使用者參與到其中,最常見的例子紅包雨,不僅僅能提升使用者的體驗,還能提升我們的產品的多元性。
然而互動性動畫經常面臨的一個問題就是,通過原生程式碼實現互動動畫是很複雜的,同時效能和相容性是不得不認真考慮的問題,比較好的解決方案還是尋求相關的框架。
不管採用什麼方式來製作動畫,最終呈現到前端頁面的無非是以下三種形式:
PS:為了簡單也可以用視訊,但除非動畫的播放場景固定,不然行動端視訊在不同app、不同機型、不同系統的播放顯示都不太一樣,容易踩不少坑。
Canvas
div
SVG
一句話總結:都是2D做圖,svg是向量圖,canvas是點陣圖。canvas 是逐畫素進行渲染的,適合遊戲。
SVG
Canvas
效能比較
前端動效開發,首先應該確定的是
動畫用途->確認動畫型別->確認繪製技術->確認動畫的實現方式。
雖然最終呈現動畫的載體(繪製技術)就三種,但實現動畫的方式卻很多,得從動畫型別出發討論動畫的實現方式:
(1)逐幀動畫(序列幀動畫)
(2)補間動畫(Tween動畫\關鍵幀動畫)
(3)SVG動畫
(4)骨骼動畫
(5)3D動畫
逐幀動畫是在時間幀上逐幀繪製幀內容,由於是一幀一幀的畫,所以逐幀動畫具有非常大的靈活性,幾乎可以表現任何想表現的內容。
由於逐幀動畫的幀序列內容不一樣,不僅增加製作負擔而且最終輸出的檔案量也很大,但它的優勢也很明顯:因為它相似與電影播放模式,很適合於表演很細膩的動畫,如3D效果、人物或動物急劇轉身等等效果。
所以逐幀動畫的實現核心是什麼,就是將我們的這些靜態的圖片進行快速的迴圈播放,形成了一個動態的動畫效果。這就是幀動畫。
我們可以將幀動畫匯出成GIF圖,GIF圖會連續播放,無法暫停,它往往用來實現小細節動畫,成本較低、使用方便。但其缺點也是很明顯的:
CSS3幀動畫是我們今天需要重點介紹的方案,最核心的是利用CSS3中Animation動畫,確切的說是使用animation-timing-function 的階梯函數 steps(number_of_steps, direction) 來實現逐幀動畫的連續播放。
幀動畫的實現原理是不斷切換視覺內圖片內容,利用視覺滯留生理現象來實現連續播放的動畫效果,下面我們來介紹製作CSS3幀動畫的幾種方案。
(1)連續切換動畫圖片地址src(不推薦)
我們將圖片放到元素的背景中(background-image),通過更改 background-image 的值實現幀的切換。但是這種方式會有以下幾個缺點,所以該方案不推薦。
(2)連續切換雪碧圖位置(推薦)我們將所有的幀動畫圖片合併成一張雪碧圖,通過改變 background-position 的值來實現動畫幀切換。分兩步進行:
步驟一:
將動畫幀合併為雪碧圖,雪碧圖的要求可以看上面素材準備,比如下面這張幀動畫雪碧圖,共20幀。
步驟二:
使用steps階梯函數切換雪碧圖位置
寫法一:
<div class="sprite"></div> .sprite { width: 300px; height: 300px; background-repeat: no-repeat; background-image: url(frame.png); animation: frame 333ms steps(1,end) both infinite; } @keyframes frame { 0% {background-position: 0 0;} 5% {background-position: -300px 0;} 10% {background-position: -600px 0;} 15% {background-position: -900px 0;} 20% {background-position: -1200px 0;} 25% {background-position: -1500px 0;} 30% {background-position: -1800px 0;} 35% {background-position: -2100px 0;} 40% {background-position: -2400px 0;} 45% {background-position: -2700px 0;} 50% {background-position: -3000px 0;} 55% {background-position: -3300px 0;} 60% {background-position: -3600px 0;} 65% {background-position: -3900px 0;} 70% {background-position: -4200px 0;} 75% {background-position: -4500px 0;} 80% {background-position: -4800px 0;} 85% {background-position: -5100px 0;} 90% {background-position: -5400px 0;} 95% {background-position: -5700px 0;} 100% {background-position: -6000px 0;} }
針對以上動畫有疑問?
問題一:既然都詳細定義關鍵幀了,是不是可以不用steps函數了,直接定義linear變化不就好了嗎?
animation: frame 10s linear both infinite;
如果我們定義成這樣,動畫是不會階梯狀,一步一步執行的,而是會連續的變化背景圖位置,是移動的效果,而不是切換的效果,如下圖:
問題二: 不是應該設定為20步嗎,怎麼變成了1?
這裡我們先來了解下animation-timing-function屬性。CSS animation-timing-function屬性定義CSS動畫在每一動畫週期中執行的節奏。
綜上我們可以知道,因為我們詳細定義了一個動畫週期,也就是說0% ~ 5%之間變化一次,5% ~ 10%變化一次,所以我們這樣寫才能達到想要的效果。
寫法二:
<div class="sprite"></div>.sprite { width: 300px; height: 300px; background-repeat: no-repeat; background-image: url(frame.png); animation: frame 333ms steps(20) both infinite; } @keyframes frame { 0% {background-position: 0 0;}//可省略 100% {background-position: -6000px 0;} }
這裡我們定義了關鍵幀的開始和結束,也就是定義了一個關鍵幀週期,但因為我們沒有詳細的定義每一幀的展示,所以我們要將0%~100%這個區間分成20步來階段性展示。
(3)連續移動雪碧圖位置(行動端推薦)
跟第二種基本一致,只是切換雪碧圖的位置過程換成了transform:translate3d()來實現,不過要加多一層overflow: hidden;的容器包裹,這裡我們以只定義初始和結束幀為例,使用transform可以開啟GPU加速,提高機器渲染效果,還能有效解決行動端幀動畫抖動的問題。
<div class="sprite-wp"> <div class="sprite"></div></div> .sprite-wp { width: 300px; height: 300px; overflow: hidden; } .sprite { width: 6000px; height: 300px; will-change: transform; background: url(frame.png) no-repeat center; animation: frame 333ms steps(20) both infinite; } @keyframes frame { 0% {transform: translate3d(0,0,0);} 100% {transform: translate3d(-6000px,0,0);} }
steps() 函數詳解
從上面的程式碼我們可以發現,CSS實現的核心就是使用animation-timing-function緩動函數的階梯函數steps(number_of_steps, direction)來實現逐幀動畫的連續播放的。
接著我們來了解下steps() 函數:
steps 指定了一個階梯函數,包含兩個引數:
除了 steps 函數,animation-timing-function 還有兩個與逐幀動畫相關的屬性值 step-start 與 step-end:
(1)通過JS來控制img的src屬性切換(不推薦)
和上面CSS3幀動畫裡面切換元素background-image屬性一樣,會存在多個請求等問題,所以該方案我們不推薦,但是這是一種解決思路。
(2)通過JS來控制canvas影象繪製
通過canvas製作幀動畫的原理是用drawImage方法將圖片繪製到canvas上,不斷擦除和重繪就能得到我們想要的效果。
<canvas id="canvas" width="300" height="300"></canvas>(function () { var timer = null, canvas = document.getElementById("canvas"), context = canvas.getContext('2d'), img = new Image(), width = 300, height = 300, k = 20, i = 0; img.src = "frame.png"; function drawImg() { context.clearRect(0, 0, width, height); i++; if (i == k) { i = 0; } context.drawImage(img, i * width, 0, width, height, 0, 0, width, height); window.requestAnimationFrame(drawImg); } img.onload = function () { window.requestAnimationFrame(drawImg); } })();
上面是通過改變裁剪影象的X座標位置來實現動畫效果的,也可以通過改變畫布上放置影象的座標位置實現,如下:
context.drawImage(img, 0, 0, width*k, height,-i*width,0,width*k,height);
(3)通過JS來控制CSS屬性值變化
這種方式和前面CSS3幀動畫一樣,有三種方式,一種是通過JS切換元素背景圖片地址background-image,一種是通過JS切換元素背景圖片定位background-position,最後一種是通過JS移動元素transform:translate3d(),第一種不做介紹,因為同樣會存在多個請求等問題,不推薦使用,這裡實現後面兩種。
切換元素背景圖片位置 background-position
.sprite { width: 300px; height: 300px; background: url(frame.png) no-repeat 0 0; } <div class="sprite" id="sprite"></div>(function(){ var sprite = document.getElementById("sprite"), picWidth = 300, k = 20, i = 0, timer = null; // 重置背景圖片位置 sprite.style = "background-position: 0 0"; // 改變背景圖位置 function changePosition(){ sprite.style = "background-position: "+(-picWidth*i)+"px 0"; i++; if(i == k){ i = 0; } window.requestAnimationFrame(changePosition); } window.requestAnimationFrame(changePosition); })();
移動元素背景圖片位置 transform:translate3d()
.sprite-wp { width: 300px; height: 300px; overflow: hidden; } .sprite { width: 6000px; height: 300px; will-change: transform; background: url(frame.png) no-repeat center; } <div class="sprite-wp"> <div class="sprite" id="sprite"></div></div> (function () { var sprite = document.getElementById("sprite"), picWidth = 300, k = 20, i = 0, timer = null; // 重置背景圖片位置 sprite.style = "transform: translate3d(0,0,0)"; // 改變背景圖移動 function changePosition() { sprite.style = "transform: translate3d(" + (-picWidth * i) + "px,0,0)"; i++; if (i == k) { i = 0; } window.requestAnimationFrame(changePosition); } window.requestAnimationFrame(changePosition); })();
我們通過Chrome瀏覽器的各種工具,檢視了每種方案的 FPS、CPU佔用率、GPU佔用、Scripting、Rendering、Painting、記憶體的使用情況,得到以下資料:
通過分析以上資料我們可以得出以下幾點:
結論:我們看到,在7個指標中,CSS transform:translate3d() 方案將其中的4個指標做到了最低,從這點看,我們完全有理由選擇這種方案來實現CSS幀動畫。
2.3.2 補間動畫(Tween動畫\關鍵幀動畫)
補間動畫是動畫的基礎形式之一,又叫做中間幀動畫,漸變動畫,指的是人為設定動畫的關鍵狀態,也就是關鍵幀,而關鍵幀之間的過渡過程只需要由計算機處理渲染的一種動畫形式。
說白了,就是我們在做動畫的時候,只需要指定幾個特殊時刻動畫的狀態,其餘的狀態由計算機自動計算補充。
實現補間動畫常見的手段主要由以下幾種:
(1)transition 動畫
transition允許CSS的屬性值在一定的時間區間內平滑地過渡,即指定元素的初始狀態 和末尾狀態,既可以完成一個動畫,中間的變化完全有瀏覽器自己決定。動畫的效果主要還是看transition相關屬性即可。
然而利用transition製作的動畫也有著顯著的缺點:
(2)animation 動畫
利用animation可以完成一個完整的CSS補間動畫,如上面所說,我們只需要定義幾個特殊時刻的動畫狀態即可。這個特殊時刻通常我們叫做關鍵幀。
keyframes 關鍵幀
Keyframes具有其自己的語法規則,他的命名是由"@keyframes"開頭,後面緊接著是這個「動畫的名稱」加上一對花括號「{}」,括號中就是一些不同時間段樣式規則,有點像我們CSS的樣式寫法一樣。
對於一個"@keyframes"中的樣式規則是由多個百分比構成的,如「0%」到"100%"之間,我們可以在這個規則中建立多個百分比,我們分別給每一個百分比中給需要有動畫效果的元素加上不同的屬性,從而讓元素達到一種在不斷變化的效果,比如說移動,改變元素顏色,位置,大小,形狀等。
不過有一點需要注意的是,我們可以使用「fromt」「to」來代表一個動畫是從哪開始,到哪結束,也就是說這個 "from"就相當於"0%"而"to"相當於"100%",值得一說的是,其中"0%"不能像別的屬性取值一樣把百分比符號省略,我們在這裡必須加上百分符號(「%」)如果沒有加上的話,我們這個keyframes是無效的,不起任何作用。因為keyframes的單位只接受百分比值。看一下具體的程式碼:
@keyframes IDENT { from { Properties:Properties value; } Percentage { Properties:Properties value; } to { Properties:Properties value; } } /*或者全部寫成百分比的形式:*/ @keyframes IDENT { 0% { Properties:Properties value; } Percentage { Properties:Properties value; } 100% { Properties:Properties value; } }
其中IDENT是一個動畫名稱,你可以隨便取,當然語意化一點更好,Percentage是百分比值,我們可以新增許多個這樣的百分比,Properties為CSS的屬性名,比如說left,background等,value就是相對應的屬性的屬性值。
利用JavaScript實現動畫,可以採用開源的JavaScript動畫庫或框架進行實現,例如:Anime.js或者TweenJS 下面我們以Anime.js為例進行演示如何實現一個補間動畫。
一定程度上,anime.js也是一個CSS3動畫庫,適用所有的CSS屬性,並且實現的@keyframes 能更方便的實現幀動畫,替代CSS3複雜的定義方式。使用物件陣列的形式定義每一幀。
anime({ targets: 'div', translateX: [ { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一幀 { value: 0, duration: 1000, delay: 500, elasticity: 0 } //第二幀 ] }) //這個例子實現了目標元素在兩幀中實現水平位移
提供的Timeline能實現更為複雜的動畫效果,通過這個Timeline,我們可以維護不同的動畫之間的關係,進而通過多個不同的動畫組成一個更為複雜的動畫。
var myTimeline = anime.timeline(); //通過.add()方法新增動畫 myTimeline .add({ targets: '.square', translateX: 250 }) .add({ targets: '.circle', translateX: 250 }) .add({ targets: '.triangle', translateX: 250 });
當我們在實現動畫的時候,慢慢會發現,大部分的元素都是圖片,而且圖片是提前預設好的,不能更改,只能用新的圖片替換,例如當我們要實現微笑動畫的時候,需要畫兩張圖,一幅是閉著嘴的,一幅是張嘴笑的,然後逐幀播放。這樣的畫面當你有足夠多幀圖片的時候,並不會看出生硬,一旦低於 24 幀就是變得不自然了,那怎麼在不增加工作量的前提下,實現流暢的變化呢?我們將關鍵幀動畫的思維嫁接到元素自身扭曲變化上,就催生出了「柔性動畫」的概念。
從上圖可以看出,元素之間是可以相互變化的,而且非常的流暢,這樣的動畫並不需要 canvas 這種重武器,簡單的 DOM 就可以實現,SVG 真的是一個神器,不僅在實現圖示,字型上特點鮮明,在實現柔性動畫方面也獨樹一幟。
SVG 依然是 DOM ,他有自己獨有的 Animation 標籤,但也支援 CSS 的屬性,其實現動畫的本質是依賴於線條和填充,線條的變化,導致填充區域的改變,從而引起形狀的變化。而線條則依賴於路徑和錨點,路徑和錨點的改變,直接影響了線條的變化。
可以用AI等SVG編輯工具生成SVG圖片後,配合anime.js、GSAP等現有庫進行動畫製作。
下面我們通過anime.js來實現一個SVG路徑動畫.
SVG 繪製路徑
var path = anime.path('.motion-path-demo path'); anime({ targets: '.motion-path-demo .el', translateX: path('x'), translateY: path('y'), rotate: path('angle'), easing: 'linear', duration: 2000, loop: true });
SVG 實現的動畫比較區域性和小巧,使用範圍也比較狹窄,但是當我們實現複雜的柔性動畫,甚至遊戲的時候,就還是需要用骨骼動畫來實現。
從上圖我們可以看到龍的翅膀是一張圖片,但是可以通過圖片的區域性的扭曲和變形,來實現煽動翅膀時帶來的肌肉收縮和舒張。這樣的動畫是怎麼實現的呢?這就要引出骨骼動畫中,一個非常重要的概念:網格。
這裡我們比較淺顯的討論下這個概念,要實現圖片的區域性變化,我們就要把圖片分塊,分的每一塊就稱為網格,每個網格都有自己的頂點和邊,頂點的位移會引起網格形狀的變化,形狀的變化就會帶來所附屬的圖片的變化。網格的概念是不是很像路徑和錨點,不論怎樣的技術,在實現邏輯上都大同小異,重要的不是一直盯著不同和變化的部分,而是發現那些不變的地方,才能達到觸類旁通的效果。
製作這樣的動畫並不複雜,你可以使用類似 Spine 和 DragonBones 這樣的工具,但是做動畫真的是一個體力活,你需要不斷的偵錯,以求達到一種讓人看起來舒服的狀態。
骨骼動畫就是把角色的各部分身體部件圖片繫結到一根根互相作用連線的「骨頭」上,通過控制這些骨骼的位置、旋轉方向和放大縮小而生成的動畫。
我們常說的骨骼動畫一般分為兩個部分:
骨架涉及的資料包括兩個:
蒙皮則表達的是依附在骨骼上的頂點的資訊。
骨骼繫結的過程就是確定每個頂點受哪幾根骨骼的影響,每根骨骼影響的權重有多大,譬如肘部的面板可能同時受大臂和小臂兩根骨頭的影響,而遠離手肘的部分可能就只受小臂骨頭影響。一般在3D骨骼動畫裡,每個頂點最多支援4-8根骨骼同時影響它就已經可以很精確地表達整個蒙皮的效果了。
骨骼動畫的優勢:
骨骼動畫比傳統的逐幀動畫要求更高的處理器效能,但同時它也具有更多的優勢:
首先我們來了解一下,骨骼動畫是如何進行製作的:
製作骨骼動畫主要是使用 Spine 和 DragonBones 這樣的工具進行製作。
DragonBones
DragonBones是從Flash動畫開始創作的,初衷是減小資源量,同時實現更為細粒度的動作(比如互動式的),讓美術從繁瑣的逐幀繪製Sprie Sheet的工作中解放出來,所以它把一個角色每一幀的sprite sheet拆分成一個個更小的基本圖塊,譬如胳膊,腿,軀幹等等,而每個基本圖塊仍然是最小的可控制單位。
以下游戲&渲染引擎都支援渲染DragonBones匯出的檔案:
Spine
Spine 是一款針對遊戲開發的 2D 骨骼動畫編輯工具。Spine 旨在提供更高效和簡潔 的工作流程,以建立遊戲所需的動畫。
業界收費專業2D骨骼動畫編輯工具,動畫設計師推薦易用穩定,以下游戲&渲染引擎都支援渲染Spine匯出的檔案:
下面我們來製作一個骨骼動畫小案例
建立骨骼
首先我們需要建立手部的骨骼,如下圖所示:
1確保左上角為SETUP模式
確保選中右邊檢視中的根骨骼,建立骨骼時必須要選中父骨骼
單擊左下角的Create按鈕
開始依次建立出5根骨骼
建立蒙皮網格
然後我們需要給手部建立蒙皮網格(MESH),如下圖所示:
首先,單擊建立骨骼的Create按鈕,退出骨骼建立模式
設定網格點權重
我們需要給網格頂點設定各個骨骼的權重,整個過程如下圖所示:
首先,關閉Edit Mesh選單
動起來!
現在我們要讓手動起來了,我們只展示一個彎曲手臂的動畫即可。
首先,我們需要設定關鍵幀,讓我們在第1幀和第30幀設定好關鍵幀,這兩個關鍵幀對應的手臂位置是完全一樣的,因為我們需要回圈播放動畫。
具體步驟如下圖:
接下來我們只需輕輕旋轉手臂,並在0-30幀中間找一個幀當做關鍵幀即可:我們選擇第15幀作為中間的關鍵幀。
額外的,我給另一隻手、嘴巴、臉部和頭髮都做了MESH,以下是動畫的效果圖:
用Spine將製作好的骨骼動畫進行匯出輸出資源(合圖資訊檔案:atlas;動畫資訊檔案:json,圖片合圖:png),將這些資源交由前端進行展示。
前端開發根據Spine或者DragonBones能夠支援的渲染引擎,在專案中匯入渲染引擎進行展示骨骼動畫。
前端3D動畫實現可以通過perspective屬性操作用CSS 3D來實現,或者直接藉助開源的Three.js開源庫進行實現。
由於3D動畫涉及的內容較多,篇幅有限,後面我們將專門開一章來講解前端3D動畫。
適合場景: 簡單的展示型動畫
使用transition\animation屬性,設定相應的關鍵幀狀態,並且藉助一些緩動函數來進行實現一些簡單化的動畫。
優點:開發成本低,不需要匯入任何額外的依賴包
缺點與不足:只能夠勝任做一些比較簡單化的動畫,無法實現一些過於負責的動畫。
適用場景: 簡單的展示型動畫+弱互動型動畫
Anime.js是一個輕量級的js驅動的動畫庫,主要的功能有:
功能介紹:
一定程度上,anime.js也是一個CSS3動畫庫,適用所有的CSS屬性,並且實現的@keyframes能更方便的實現幀動畫,替代CSS3複雜的定義方式。使用物件陣列的形式定義每一幀。
anime({ targets: 'div', translateX: [ { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一幀 { value: 0, duration: 1000, delay: 500, elasticity: 0 } //第二幀 ] }) //這個例子實現了目標元素在兩幀中實現水平位移
提供的Timeline能實現更為複雜的動畫效果,通過這個Timeline,我們可以維護不同的動畫之間的關係,進而通過多個不同的動畫組成一個更為複雜的動畫。
var myTimeline = anime.timeline(); //通過.add()方法新增動畫 myTimeline .add({ targets: '.square', translateX: 250 }) .add({ targets: '.circle', translateX: 250 }) .add({ targets: '.triangle', translateX: 250 });
動畫播放的控制,常見的有暫停,重播,繼續,動畫狀態的跟蹤,自動播放,迴圈次數,抖動效果
為動畫提供了回撥函數,在動畫或時間線完成的開始,期間或之時執行回撥函數。
var myAnimation = anime({ targets: '#begin .el', translateX: 250, delay: 1000, begin: function(anim) { // callback console.log(anim.began); // true after 1000ms } });
支援promise,動畫結束後,呼叫anime.finished會返回一個promise物件。
支援svg繪製路徑,目前不支援canvas繪製。
對於input這樣帶有數值的元素標籤,也可以通過anime範例來設定動畫。
anime({ targets: input, value: 1000, // Animate the input value to 1000 round: 1 // Remove decimals by rounding the value });
優點:
缺點:
Anime.js做展示型動畫是可以勝任的,但是對於特別複雜的動畫也是不太能夠實現,在做互動性動畫方面還是需要看場景,它更多適合做一些小型的互動動畫,類似於通過觸控式螢幕幕踢足球這種強互動的,anime.js就不是很有優勢了。
適用場景: 複雜的展示型動畫
通過 AE 上的 Bodymovin 外掛將 AE 中製作好的動畫匯出成一個 json 檔案,通過Lottie對JSON進行解析,最後以SVG/canvas/html的方式渲染動畫。
能夠完好的展示設計師設計的各種各樣複雜的動畫。
優點:
缺點:
適用場景: 互動型動畫,動畫小遊戲
PixiJS是一個2D 渲染引擎, Pixi 主要負責渲染畫面。可以建立豐富的互動式圖形,動畫和遊戲,而無需深入瞭解WebGL API或處理瀏覽器和裝置相容性的問題。與此同時,PixiJS具有完整的WebGL支援,如果需要,可以無縫地回退到HTML5的canvas。PixiJs預設使用WebGL渲染,也可以通過宣告指定canvas渲染,WebGL在行動端Android 4.4 browser並不支援,不過可以使用canvas優雅降級。
特性(摘自官方DOCS):
優點:
缺點:
效能:
對於手機版本Android4.4 以上的手機,除了程式碼層面造成的效能不足,通過WebGL呼叫GPU渲染,效能還是有保障的。然而對於Android4.4只能使用canvas渲染,效能還是要看動畫的複雜度,以及程式碼的優化
簡單的展示型動畫:對於比較簡單的動畫,我們可以先嚐試使用原生CSS的transition\animation屬性來進行實現。
簡單的展示型動畫+弱互動:對於簡單的動畫展示並且需要有簡單的互動行為,比如使用者點選一下暫停執行相應操作,待操作完成繼續播放動畫,互動方面比較偏弱,可以採用Anime.js的方案。
Anime.js不僅僅支援所有的CSS屬性,而且可以通過Timeline,callback, playback controls來控制動畫執行的各個狀態,並且Anime.js可以配合實現SVG動畫。
複雜的展示型動畫:
強互動&互動小遊戲&骨骼動畫: