作者:vivo 互聯(lián)網(wǎng)前端團(tuán)隊(duì)- ZhaoJie
本文將從各個(gè)角度來對(duì)動(dòng)畫整個(gè)體系進(jìn)行分類,并且介紹各種前端動(dòng)畫的實(shí)現(xiàn)方法,最后我們將總結(jié)在實(shí)際開發(fā)中的各個(gè)場(chǎng)景的動(dòng)畫選擇方案。
一、背景
前端動(dòng)畫場(chǎng)景需求多
對(duì)眾多動(dòng)畫場(chǎng)景的技術(shù)實(shí)現(xiàn)方案選擇上比較模糊
各動(dòng)畫方案的優(yōu)劣及適用場(chǎng)景認(rèn)識(shí)模糊
現(xiàn)有動(dòng)畫庫(kù)太多,不知道選哪個(gè)
主流動(dòng)畫庫(kù)的適用場(chǎng)景認(rèn)識(shí)模糊
下面首先讓我們從各個(gè)角度來對(duì)動(dòng)畫整個(gè)體系進(jìn)行分類,讓我們清晰的了解動(dòng)畫整個(gè)體系。
二、分類
2.1 ?用途角度
首先我們從動(dòng)畫的用途或者說是業(yè)務(wù)的角度來進(jìn)行區(qū)分,將我們平時(shí)的動(dòng)畫分為展示型動(dòng)畫和交互型動(dòng)畫。
2.1.1 展示型動(dòng)畫
類似于一張GIF圖,或者一段視頻。比如在開啟寶箱的時(shí)候,我們會(huì)加入一個(gè)切場(chǎng)過渡動(dòng)畫,來替代原有的生硬等待結(jié)果。
展示型動(dòng)畫在實(shí)際使用的場(chǎng)景中,實(shí)現(xiàn)的方法很多,比如用GIF圖,canvas,CSS3動(dòng)畫等,但是最終輸出的結(jié)果是不帶有交互的,也就是從動(dòng)畫起始狀態(tài)到結(jié)束狀態(tài)一氣呵成,這個(gè)過程用戶可以感知,但是無法參與。
2.1.2 交互型動(dòng)畫
用戶自已參與的,對(duì)于交互性動(dòng)畫而言,我們可以在動(dòng)畫播放的某個(gè)時(shí)間節(jié)點(diǎn)觸發(fā)相應(yīng)的操作,進(jìn)而讓用戶參與到其中,最常見的例子紅包雨,不僅僅能提升用戶的體驗(yàn),還能提升我們的產(chǎn)品的多元性。
然而交互性動(dòng)畫經(jīng)常面臨的一個(gè)問題就是,通過原生代碼實(shí)現(xiàn)交互動(dòng)畫是很復(fù)雜的,同時(shí)性能和兼容性是不得不認(rèn)真考慮的問題,比較好的解決方案還是尋求相關(guān)的框架。
2.2 繪制技術(shù)角度
不管采用什么方式來制作動(dòng)畫,最終呈現(xiàn)到前端頁(yè)面的無非是以下三種形式:
Canvas
div
SVG
PS:為了簡(jiǎn)單也可以用視頻,但除非動(dòng)畫的播放場(chǎng)景固定,不然移動(dòng)端視頻在不同app、不同機(jī)型、不同系統(tǒng)的播放顯示都不太一樣,容易踩不少坑。
2.2.1 不同繪制技術(shù)的性能差異
Canvas
效率高、性能好、可控性高,只能處理位圖,內(nèi)存占用恒定
依賴分辨率
不支持事件處理器
弱的文本渲染能力
能夠以 .png 或 .jpg 格式保存結(jié)果圖像
最適合圖像密集型的游戲,其中的許多對(duì)象會(huì)被頻繁重繪
div
包括CSS控制的DOM動(dòng)畫、JS控制的DOM動(dòng)畫
比較適合簡(jiǎn)單的數(shù)量較少的復(fù)雜度較低的動(dòng)畫
SVG
處理矢量圖,不失真
不依賴分辨率
支持事件處理器
最適合帶有大型渲染區(qū)域的應(yīng)用程序(比如谷歌地圖)
復(fù)雜度高會(huì)減慢渲染速度(任何過度使用 DOM 的應(yīng)用都不快)
不適合游戲應(yīng)用
2.2.2? Canvas和SVG比較
一句話總結(jié):都是2D做圖,svg是矢量圖,canvas是位圖。canvas 是逐像素進(jìn)行渲染的,適合游戲。
SVG
SVG繪制的是矢量圖,縮放不影響顯示,所以最適合帶有大型渲染區(qū)域的應(yīng)用程序(比如谷歌地圖)
SVG 是一種使用 XML 描述 2D 圖形的語(yǔ)言。
SVG 基于 XML,這意味著 SVG DOM 中的每個(gè)元素都是可用的。您可以為某個(gè)元素附加 JavaScript 事件處理器。
在 SVG 中,每個(gè)被繪制的圖形均被視為對(duì)象。如果 SVG 對(duì)象的屬性發(fā)生變化,那么瀏覽器能夠自動(dòng)重現(xiàn)圖形。
Canvas
Canvas 通過 JavaScript 來繪制 2D 圖形。
Canvas 是逐像素進(jìn)行渲染的。
在 Canvas 中,一旦圖形被繪制完成,它就不會(huì)繼續(xù)得到瀏覽器的關(guān)注。如果其位置發(fā)生變化,那么整個(gè)場(chǎng)景也需要重新繪制,包括任何或許已被圖形覆蓋的對(duì)象。
Canvas只占用一個(gè)DOM節(jié)點(diǎn),在做一些煙花、飄雪等運(yùn)動(dòng)元素很多的動(dòng)畫時(shí),會(huì)比CSS/SVG性能好。
性能比較
一般情況下,隨著屏幕大小的增大,canvas將開始降級(jí),因?yàn)樾枰L制更多的像素。
隨著屏幕上的對(duì)象數(shù)目增多,SVG 將開始降級(jí),因?yàn)槲覀冋粩鄬⑦@些對(duì)象添加到 DOM 中。
這些度量不一定準(zhǔn)確,以下方面的不同一定會(huì)引起變化:實(shí)現(xiàn)和平臺(tái)、是否使用完全硬件加速的圖形,以及 JavaScript 引擎的速度。
2.3 動(dòng)畫類型角度
前端動(dòng)效開發(fā),首先應(yīng)該確定的是
動(dòng)畫用途->確認(rèn)動(dòng)畫類型->確認(rèn)繪制技術(shù)->確認(rèn)動(dòng)畫的實(shí)現(xiàn)方式。
雖然最終呈現(xiàn)動(dòng)畫的載體(繪制技術(shù))就三種,但實(shí)現(xiàn)動(dòng)畫的方式卻很多,得從動(dòng)畫類型出發(fā)討論動(dòng)畫的實(shí)現(xiàn)方式:
(1)逐幀動(dòng)畫(序列幀動(dòng)畫)
GIF實(shí)現(xiàn)
CSS實(shí)現(xiàn)(animation)
JS+DOM實(shí)現(xiàn)
JS+canvas實(shí)現(xiàn)
(2)補(bǔ)間動(dòng)畫(Tween動(dòng)畫關(guān)鍵幀動(dòng)畫)
CSS實(shí)現(xiàn)(transition、animation等)使用一些緩動(dòng)函數(shù)
JS實(shí)現(xiàn)
(3)SVG動(dòng)畫
使用 XML 格式定義圖形
可以用AI等SVG編輯工具生成SVG圖片后,配合anime.js、GSAP等現(xiàn)有庫(kù)進(jìn)行動(dòng)畫制作
(4)骨骼動(dòng)畫
一般采用Spine、DragonBones等工具導(dǎo)出相應(yīng)資源圖片和JSON動(dòng)畫配置資源后使用。
(5)3D動(dòng)畫
DOM操作用CSS 3D實(shí)現(xiàn)。(perspective屬性、css3d-engine)
場(chǎng)景搭建用webGL(Three.js等)
3D模型動(dòng)畫用Blender或maya等制作完成后導(dǎo)出使用
2.3.1 逐幀動(dòng)畫(序列幀動(dòng)畫)
逐幀動(dòng)畫是在時(shí)間幀上逐幀繪制幀內(nèi)容,由于是一幀一幀的畫,所以逐幀動(dòng)畫具有非常大的靈活性,幾乎可以表現(xiàn)任何想表現(xiàn)的內(nèi)容。
由于逐幀動(dòng)畫的幀序列內(nèi)容不一樣,不僅增加制作負(fù)擔(dān)而且最終輸出的文件量也很大,但它的優(yōu)勢(shì)也很明顯:因?yàn)樗嗨婆c電影播放模式,很適合于表演很細(xì)膩的動(dòng)畫,如3D效果、人物或動(dòng)物急劇轉(zhuǎn)身等等效果。
所以逐幀動(dòng)畫的實(shí)現(xiàn)核心是什么,就是將我們的這些靜態(tài)的圖片進(jìn)行快速的循環(huán)播放,形成了一個(gè)動(dòng)態(tài)的動(dòng)畫效果。這就是幀動(dòng)畫。
2.3.1.1 GIF實(shí)現(xiàn)
我們可以將幀動(dòng)畫導(dǎo)出成GIF圖,GIF圖會(huì)連續(xù)播放,無法暫停,它往往用來實(shí)現(xiàn)小細(xì)節(jié)動(dòng)畫,成本較低、使用方便。但其缺點(diǎn)也是很明顯的:
畫質(zhì)上,GIF 支持顏色少(最大256色)、Alpha 透明度支持差,圖像鋸齒毛邊比較嚴(yán)重;
交互上,不能直接控制播放、暫停、播放次數(shù),靈活性差;
性能上,GIF 會(huì)引起頁(yè)面周期性的繪畫,性能較差。
2.3.1.2 CSS實(shí)現(xiàn)
CSS3幀動(dòng)畫是我們今天需要重點(diǎn)介紹的方案,最核心的是利用CSS3中Animation動(dòng)畫,確切的說是使用animation-timing-function?的階梯函數(shù)?steps(number_of_steps, direction)?來實(shí)現(xiàn)逐幀動(dòng)畫的連續(xù)播放。
幀動(dòng)畫的實(shí)現(xiàn)原理是不斷切換視覺內(nèi)圖片內(nèi)容,利用視覺滯留生理現(xiàn)象來實(shí)現(xiàn)連續(xù)播放的動(dòng)畫效果,下面我們來介紹制作CSS3幀動(dòng)畫的幾種方案。
(1)連續(xù)切換動(dòng)畫圖片地址src(不推薦)
我們將圖片放到元素的背景中(background-image),通過更改?background-image?的值實(shí)現(xiàn)幀的切換。但是這種方式會(huì)有以下幾個(gè)缺點(diǎn),所以該方案不推薦。
多張圖片會(huì)帶來多個(gè) HTTP 請(qǐng)求
每張圖片首次加載會(huì)造成圖片切換時(shí)的閃爍
不利于文件的管理
(2)連續(xù)切換雪碧圖位置(推薦)
我們將所有的幀動(dòng)畫圖片合并成一張雪碧圖,通過改變?background-position?的值來實(shí)現(xiàn)動(dòng)畫幀切換。分兩步進(jìn)行:
步驟一:
將動(dòng)畫幀合并為雪碧圖,雪碧圖的要求可以看上面素材準(zhǔn)備,比如下面這張幀動(dòng)畫雪碧圖,共20幀。
(圖片來源于:幀動(dòng)畫的多種實(shí)現(xiàn)方式與性能對(duì)比)
步驟二:
使用steps階梯函數(shù)切換雪碧圖位置
寫法一:
.sprite { width: 300px; height: 300px; background-repeat: no-repeat; 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;} }
針對(duì)以上動(dòng)畫有疑問?
問題一:既然都詳細(xì)定義關(guān)鍵幀了,是不是可以不用steps函數(shù)了,直接定義linear變化不就好了嗎?
animation: frame 10s linear both infinite;
如果我們定義成這樣,動(dòng)畫是不會(huì)階梯狀,一步一步執(zhí)行的,而是會(huì)連續(xù)的變化背景圖位置,是移動(dòng)的效果,而不是切換的效果,如下圖:
問題二:?不是應(yīng)該設(shè)置為20步嗎,怎么變成了1?
這里我們先來了解下animation-timing-function屬性。CSS animation-timing-function屬性定義CSS動(dòng)畫在每一動(dòng)畫周期中執(zhí)行的節(jié)奏。
綜上我們可以知道,因?yàn)槲覀冊(cè)敿?xì)定義了一個(gè)動(dòng)畫周期,也就是說0% ~ 5%之間變化一次,5% ~ 10%變化一次,所以我們這樣寫才能達(dá)到想要的效果。
寫法二:
?
?
.sprite { width: 300px; height: 300px; background-repeat: no-repeat; animation: frame 333ms steps(20) both infinite; } @keyframes frame { 0% {background-position: 0 0;}//可省略 100% {background-position: -6000px 0;} }
這里我們定義了關(guān)鍵幀的開始和結(jié)束,也就是定義了一個(gè)關(guān)鍵幀周期,但因?yàn)槲覀儧]有詳細(xì)的定義每一幀的展示,所以我們要將0%~100%這個(gè)區(qū)間分成20步來階段性展示。
(3)連續(xù)移動(dòng)雪碧圖位置(移動(dòng)端推薦)
跟第二種基本一致,只是切換雪碧圖的位置過程換成了transform:translate3d()來實(shí)現(xiàn),不過要加多一層overflow: hidden;的容器包裹,這里我們以只定義初始和結(jié)束幀為例,使用transform可以開啟GPU加速,提高機(jī)器渲染效果,還能有效解決移動(dòng)端幀動(dòng)畫抖動(dòng)的問題。
.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() 函數(shù)詳解
從上面的代碼我們可以發(fā)現(xiàn),CSS實(shí)現(xiàn)的核心就是使用animation-timing-function緩動(dòng)函數(shù)的階梯函數(shù)steps(number_of_steps, direction)來實(shí)現(xiàn)逐幀動(dòng)畫的連續(xù)播放的。
接著我們來了解下steps() 函數(shù):
steps 指定了一個(gè)階梯函數(shù),包含兩個(gè)參數(shù):
第一個(gè)參數(shù)指定了函數(shù)中的間隔數(shù)量(必須是正整數(shù));
第二個(gè)參數(shù)可選,指定在每個(gè)間隔的起點(diǎn)或是終點(diǎn)發(fā)生階躍變化,接受 start 和 end 兩個(gè)值,默認(rèn)為 end。
start 第一幀是第一步動(dòng)畫的結(jié)束,end 第一幀是第一步動(dòng)畫的開始。
除了 steps 函數(shù),animation-timing-function 還有兩個(gè)與逐幀動(dòng)畫相關(guān)的屬性值 step-start 與 step-end:
step-start 等同于 steps(1,start)
step-end 等同于 steps(1,end)
2.3.1.3 JS實(shí)現(xiàn)
(1)通過JS來控制img的src屬性切換(不推薦)
和上面CSS3幀動(dòng)畫里面切換元素background-image屬性一樣,會(huì)存在多個(gè)請(qǐng)求等問題,所以該方案我們不推薦,但是這是一種解決思路。
(2)通過JS來控制canvas圖像繪制
通過canvas制作幀動(dòng)畫的原理是用drawImage方法將圖片繪制到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坐標(biāo)位置來實(shí)現(xiàn)動(dòng)畫效果的,也可以通過改變畫布上放置圖像的坐標(biāo)位置實(shí)現(xiàn),如下:
context.drawImage(img, 0, 0, width*k, height,-i*width,0,width*k,height);
(3)通過JS來控制CSS屬性值變化
這種方式和前面CSS3幀動(dòng)畫一樣,有三種方式,一種是通過JS切換元素背景圖片地址background-image,一種是通過JS切換元素背景圖片定位background-position,最后一種是通過JS移動(dòng)元素transform:translate3d(),第一種不做介紹,因?yàn)橥瑯訒?huì)存在多個(gè)請(qǐng)求等問題,不推薦使用,這里實(shí)現(xiàn)后面兩種。
切換元素背景圖片位置?background-position
.sprite { width: 300px; height: 300px; background: url(frame.png) no-repeat 0 0; } (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); })();
移動(dòng)元素背景圖片位置?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; }(function () { var sprite = document.getElementById("sprite"), picWidth = 300, k = 20, i = 0, timer = null; // 重置背景圖片位置 sprite.style = "transform: translate3d(0,0,0)"; // 改變背景圖移動(dòng) function changePosition() { sprite.style = "transform: translate3d(" + (-picWidth * i) + "px,0,0)"; i++; if (i == k) { i = 0; } window.requestAnimationFrame(changePosition); } window.requestAnimationFrame(changePosition); })();
2.3.1.4 性能分析
我們通過Chrome瀏覽器的各種工具,查看了每種方案的 FPS、CPU占用率、GPU占用、Scripting、Rendering、Painting、內(nèi)存的使用情況,得到以下數(shù)據(jù):
通過分析以上數(shù)據(jù)我們可以得出以下幾點(diǎn):
除了CSS?transform:translate3d()?方案,其他方案的FPS都能達(dá)到60FPS的流暢程度,但該方案的FPS 也不是很低。
CPU占用率最低的方案是
CSS?transform:translate3d()?方案。
GPU占用最低的方案是JS canvas 繪制方案。
CSS 方案沒有腳本開銷。
Rendering 最少的是
CSS?transform:translate3d()?方案。
Painting 最少的是
CSS?transform:translate3d()?方案。
各方案內(nèi)存占用區(qū)別不大。
結(jié)論:我們看到,在7個(gè)指標(biāo)中,CSS?transform:translate3d()?方案將其中的4個(gè)指標(biāo)做到了最低,從這點(diǎn)看,我們完全有理由選擇這種方案來實(shí)現(xiàn)CSS幀動(dòng)畫。
2.3.2 補(bǔ)間動(dòng)畫(Tween動(dòng)畫關(guān)鍵幀動(dòng)畫)
補(bǔ)間動(dòng)畫是動(dòng)畫的基礎(chǔ)形式之一,又叫做中間幀動(dòng)畫,漸變動(dòng)畫,指的是人為設(shè)定動(dòng)畫的關(guān)鍵狀態(tài),也就是關(guān)鍵幀,而關(guān)鍵幀之間的過渡過程只需要由計(jì)算機(jī)處理渲染的一種動(dòng)畫形式。
說白了,就是我們?cè)谧鰟?dòng)畫的時(shí)候,只需要指定幾個(gè)特殊時(shí)刻動(dòng)畫的狀態(tài),其余的狀態(tài)由計(jì)算機(jī)自動(dòng)計(jì)算補(bǔ)充。
實(shí)現(xiàn)補(bǔ)間動(dòng)畫常見的手段主要由以下幾種:
CSS3 Animation:通過animation(除steps()以外的時(shí)間函數(shù))屬性在每個(gè)關(guān)鍵幀之間插入補(bǔ)間動(dòng)畫。
CSS3 Transition:區(qū)別于animation,transition只能設(shè)定初始和結(jié)束時(shí)刻的兩個(gè)關(guān)鍵幀狀態(tài)。
利用JavaScript實(shí)現(xiàn)動(dòng)畫:例如JavaScript動(dòng)畫庫(kù)或框架,Anime.js 或者TweenJS,它是CreateJS的其中一個(gè)套件。另外,在Flash業(yè)界久負(fù)盛名的GreenSock推出的GSAP(GreenSock Animation Platform)也新引入了對(duì)Javascript動(dòng)畫的支持。
2.3.2.1 CSS實(shí)現(xiàn)
(1)transition 動(dòng)畫
transition允許CSS的屬性值在一定的時(shí)間區(qū)間內(nèi)平滑地過渡,即指定元素的初始狀態(tài) 和末尾狀態(tài),既可以完成一個(gè)動(dòng)畫,中間的變化完全有瀏覽器自己決定。動(dòng)畫的效果主要還是看transition相關(guān)屬性即可。
然而利用transition制作的動(dòng)畫也有著顯著的缺點(diǎn):
transition需要事件觸發(fā),所以沒法在網(wǎng)頁(yè)加載時(shí)自動(dòng)發(fā)生。
transition是一次性的,不能重復(fù)發(fā)生,除非一再觸發(fā)。
transition只能定義開始狀態(tài)和結(jié)束狀態(tài),不能定義中間狀態(tài),也就是說只有兩個(gè)狀態(tài)。
一條transition規(guī)則,只能定義一個(gè)屬性的變化,不能涉及多個(gè)屬性。
(2)animation 動(dòng)畫
利用animation可以完成一個(gè)完整的CSS補(bǔ)間動(dòng)畫,如上面所說,我們只需要定義幾個(gè)特殊時(shí)刻的動(dòng)畫狀態(tài)即可。這個(gè)特殊時(shí)刻通常我們叫做關(guān)鍵幀。
keyframes 關(guān)鍵幀
Keyframes具有其自己的語(yǔ)法規(guī)則,他的命名是由"@keyframes"開頭,后面緊接著是這個(gè)“動(dòng)畫的名稱”加上一對(duì)花括號(hào)“{}”,括號(hào)中就是一些不同時(shí)間段樣式規(guī)則,有點(diǎn)像我們CSS的樣式寫法一樣。
對(duì)于一個(gè)"@keyframes"中的樣式規(guī)則是由多個(gè)百分比構(gòu)成的,如“0%”到"100%"之間,我們可以在這個(gè)規(guī)則中創(chuàng)建多個(gè)百分比,我們分別給每一個(gè)百分比中給需要有動(dòng)畫效果的元素加上不同的屬性,從而讓元素達(dá)到一種在不斷變化的效果,比如說移動(dòng),改變?cè)仡伾恢?,大小,形狀等?/p>
不過有一點(diǎn)需要注意的是,我們可以使用“fromt”“to”來代表一個(gè)動(dòng)畫是從哪開始,到哪結(jié)束,也就是說這個(gè) "from"就相當(dāng)于"0%"而"to"相當(dāng)于"100%",值得一說的是,其中"0%"不能像別的屬性取值一樣把百分比符號(hào)省略,我們?cè)谶@里必須加上百分符號(hào)(“%”)如果沒有加上的話,我們這個(gè)keyframes是無效的,不起任何作用。因?yàn)閗eyframes的單位只接受百分比值。看一下具體的代碼:
@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是一個(gè)動(dòng)畫名稱,你可以隨便取,當(dāng)然語(yǔ)義化一點(diǎn)更好,Percentage是百分比值,我們可以添加許多個(gè)這樣的百分比,Properties為CSS的屬性名,比如說left,background等,value就是相對(duì)應(yīng)的屬性的屬性值。
2.3.2.2 JS實(shí)現(xiàn)
利用JavaScript實(shí)現(xiàn)動(dòng)畫,可以采用開源的JavaScript動(dòng)畫庫(kù)或框架進(jìn)行實(shí)現(xiàn),例如:Anime.js或者TweenJS 下面我們以Anime.js為例進(jìn)行演示如何實(shí)現(xiàn)一個(gè)補(bǔ)間動(dòng)畫。
一定程度上,anime.js也是一個(gè)CSS3動(dòng)畫庫(kù),適用所有的CSS屬性,并且實(shí)現(xiàn)的@keyframes 能更方便的實(shí)現(xiàn)幀動(dòng)畫,替代CSS3復(fù)雜的定義方式。使用對(duì)象數(shù)組的形式定義每一幀。
戳我:keyframes實(shí)例
anime({ targets: 'div', translateX: [ { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一幀 { value: 0, duration: 1000, delay: 500, elasticity: 0 } //第二幀 ] }) //這個(gè)例子實(shí)現(xiàn)了目標(biāo)元素在兩幀中實(shí)現(xiàn)水平位移
提供的Timeline能實(shí)現(xiàn)更為復(fù)雜的動(dòng)畫效果,通過這個(gè)Timeline,我們可以維護(hù)不同的動(dòng)畫之間的關(guān)系,進(jìn)而通過多個(gè)不同的動(dòng)畫組成一個(gè)更為復(fù)雜的動(dòng)畫。
戳我:Timeline實(shí)例
var myTimeline = anime.timeline(); //通過.add()方法添加動(dòng)畫 myTimeline .add({ targets: '.square', translateX: 250 }) .add({ targets: '.circle', translateX: 250 }) .add({ targets: '.triangle', translateX: 250 });
2.3.3 SVG動(dòng)畫
當(dāng)我們?cè)趯?shí)現(xiàn)動(dòng)畫的時(shí)候,慢慢會(huì)發(fā)現(xiàn),大部分的元素都是圖片,而且圖片是提前預(yù)設(shè)好的,不能更改,只能用新的圖片替換,例如當(dāng)我們要實(shí)現(xiàn)微笑動(dòng)畫的時(shí)候,需要畫兩張圖,一幅是閉著嘴的,一幅是張嘴笑的,然后逐幀播放。這樣的畫面當(dāng)你有足夠多幀圖片的時(shí)候,并不會(huì)看出生硬,一旦低于 24 幀就是變得不自然了,那怎么在不增加工作量的前提下,實(shí)現(xiàn)流暢的變化呢?我們將關(guān)鍵幀動(dòng)畫的思維嫁接到元素自身扭曲變化上,就催生出了「柔性動(dòng)畫」的概念。
2.3.3.1 SVG動(dòng)畫講解
(圖片來源于:GSAP官網(wǎng))
從上圖可以看出,元素之間是可以相互變化的,而且非常的流暢,這樣的動(dòng)畫并不需要 canvas 這種重武器,簡(jiǎn)單的 DOM 就可以實(shí)現(xiàn),SVG 真的是一個(gè)神器,不僅在實(shí)現(xiàn)圖標(biāo),字體上特點(diǎn)鮮明,在實(shí)現(xiàn)柔性動(dòng)畫方面也獨(dú)樹一幟。
SVG 依然是 DOM ,他有自己獨(dú)有的 Animation 標(biāo)簽,但也支持 CSS 的屬性,其實(shí)現(xiàn)動(dòng)畫的本質(zhì)是依賴于線條和填充,線條的變化,導(dǎo)致填充區(qū)域的改變,從而引起形狀的變化。而線條則依賴于路徑和錨點(diǎn),路徑和錨點(diǎn)的改變,直接影響了線條的變化。
可以用AI等SVG編輯工具生成SVG圖片后,配合anime.js、GSAP等現(xiàn)有庫(kù)進(jìn)行動(dòng)畫制作。
下面我們通過anime.js來實(shí)現(xiàn)一個(gè)SVG路徑動(dòng)畫.
SVG 繪制路徑
戳我:SVG實(shí)例
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 });
(圖片來源于:animejs官網(wǎng))
2.3.4 骨骼動(dòng)畫
SVG 實(shí)現(xiàn)的動(dòng)畫比較局部和小巧,使用范圍也比較狹窄,但是當(dāng)我們實(shí)現(xiàn)復(fù)雜的柔性動(dòng)畫,甚至游戲的時(shí)候,就還是需要用骨骼動(dòng)畫來實(shí)現(xiàn)。
(圖片來源于:DragonBones官網(wǎng))
從上圖我們可以看到龍的翅膀是一張圖片,但是可以通過圖片的局部的扭曲和變形,來實(shí)現(xiàn)煽動(dòng)翅膀時(shí)帶來的肌肉收縮和舒張。這樣的動(dòng)畫是怎么實(shí)現(xiàn)的呢?這就要引出骨骼動(dòng)畫中,一個(gè)非常重要的概念:網(wǎng)格。
這里我們比較淺顯的討論下這個(gè)概念,要實(shí)現(xiàn)圖片的局部變化,我們就要把圖片分塊,分的每一塊就稱為網(wǎng)格,每個(gè)網(wǎng)格都有自己的頂點(diǎn)和邊,頂點(diǎn)的位移會(huì)引起網(wǎng)格形狀的變化,形狀的變化就會(huì)帶來所附屬的圖片的變化。網(wǎng)格的概念是不是很像路徑和錨點(diǎn),不論怎樣的技術(shù),在實(shí)現(xiàn)邏輯上都大同小異,重要的不是一直盯著不同和變化的部分,而是發(fā)現(xiàn)那些不變的地方,才能達(dá)到觸類旁通的效果。
制作這樣的動(dòng)畫并不復(fù)雜,你可以使用類似 Spine 和 DragonBones 這樣的工具,但是做動(dòng)畫真的是一個(gè)體力活,你需要不斷的調(diào)試,以求達(dá)到一種讓人看起來舒服的狀態(tài)。
2.3.4.1 骨骼動(dòng)畫講解
骨骼動(dòng)畫就是把角色的各部分身體部件圖片綁定到一根根互相作用連接的“骨頭”上,通過控制這些骨骼的位置、旋轉(zhuǎn)方向和放大縮小而生成的動(dòng)畫。
我們常說的骨骼動(dòng)畫一般分為兩個(gè)部分:
骨架(Skeleton)
蒙皮(Skin)
骨架涉及的數(shù)據(jù)包括兩個(gè):
一是骨架的拓?fù)浣Y(jié)構(gòu)(連接、父子關(guān)系)。
二是骨架的各種pose,也就是每個(gè)動(dòng)作對(duì)應(yīng)的整個(gè)骨架的位置信息。
蒙皮則表達(dá)的是依附在骨骼上的頂點(diǎn)的信息。
骨骼綁定的過程就是確定每個(gè)頂點(diǎn)受哪幾根骨骼的影響,每根骨骼影響的權(quán)重有多大,譬如肘部的皮膚可能同時(shí)受大臂和小臂兩根骨頭的影響,而遠(yuǎn)離手肘的部分可能就只受小臂骨頭影響。一般在3D骨骼動(dòng)畫里,每個(gè)頂點(diǎn)最多支持4-8根骨骼同時(shí)影響它就已經(jīng)可以很精確地表達(dá)整個(gè)蒙皮的效果了。
骨骼動(dòng)畫的優(yōu)勢(shì):
骨骼動(dòng)畫比傳統(tǒng)的逐幀動(dòng)畫要求更高的處理器性能,但同時(shí)它也具有更多的優(yōu)勢(shì):
動(dòng)畫更加生動(dòng)逼真。
圖片資源占最小的存儲(chǔ)空曠:骨骼動(dòng)畫的圖片容量可以減少90%(配置文件H5的壓縮方案后面詳解)。
動(dòng)畫切換自動(dòng)補(bǔ)間:過渡動(dòng)畫自動(dòng)生成,讓動(dòng)作更加靈動(dòng)。
骨骼可控 :可以通過代碼控制骨骼,輕松實(shí)現(xiàn)角色裝備更換,甚至可對(duì)某骨骼做特殊控制或事件監(jiān)聽。
骨骼事件幀:動(dòng)畫執(zhí)行到某個(gè)動(dòng)作或某個(gè)幀,觸發(fā)自定義事件行為。
動(dòng)作數(shù)據(jù)繼承:多角色可共用一套動(dòng)畫數(shù)據(jù)。
可結(jié)合物理引擎和碰撞檢測(cè)。
2.3.4.2 骨骼動(dòng)畫制作
首先我們來了解一下,骨骼動(dòng)畫是如何進(jìn)行制作的:
制作骨骼動(dòng)畫主要是使用 Spine 和 DragonBones 這樣的工具進(jìn)行制作。
DragonBones
(圖片來源于:DragonBones官網(wǎng))
DragonBones是從Flash動(dòng)畫開始創(chuàng)作的,初衷是減小資源量,同時(shí)實(shí)現(xiàn)更為細(xì)粒度的動(dòng)作(比如交互式的),讓美術(shù)從繁瑣的逐幀繪制Sprie Sheet的工作中解放出來,所以它把一個(gè)角色每一幀的sprite sheet拆分成一個(gè)個(gè)更小的基本圖塊,譬如胳膊,腿,軀干等等,而每個(gè)基本圖塊仍然是最小的可控制單位。
以下游戲&渲染引擎都支持渲染DragonBones導(dǎo)出的文件:
(圖片來源于:DragonBones官網(wǎng))
Spine
(圖片來源于:Spine官網(wǎng))
Spine 是一款針對(duì)游戲開發(fā)的 2D 骨骼動(dòng)畫編輯工具。Spine 旨在提供更高效和簡(jiǎn)潔 的工作流程,以創(chuàng)建游戲所需的動(dòng)畫。
業(yè)界收費(fèi)專業(yè)2D骨骼動(dòng)畫編輯工具,動(dòng)畫設(shè)計(jì)師推薦易用穩(wěn)定,以下游戲&渲染引擎都支持渲染Spine導(dǎo)出的文件:
(圖片來源于:Spine官網(wǎng))
下面我們來制作一個(gè)骨骼動(dòng)畫小案例
創(chuàng)建骨骼
首先我們需要?jiǎng)?chuàng)建手部的骨骼,如下圖所示:
1確保左上角為SETUP模式
確保選中右邊視圖中的根骨骼,創(chuàng)建骨骼時(shí)必須要選中父骨骼
單擊左下角的Create按鈕
開始依次創(chuàng)建出5根骨骼
創(chuàng)建蒙皮網(wǎng)格
然后我們需要給手部創(chuàng)建蒙皮網(wǎng)格(MESH),如下圖所示:?
首先,單擊創(chuàng)建骨骼的Create按鈕,退出骨骼創(chuàng)建模式
選中手部貼圖(Attachment)
勾選其底部的Mesh選項(xiàng)
單擊右下角的Edit按鈕
呼出了Edit Mesh菜單
勾選Edit Mesh菜單中的Deformed選項(xiàng)
單擊Edit Mesh菜單中的Create按鈕
開始在手部創(chuàng)建網(wǎng)格頂點(diǎn)
可以單擊Edit Mesh菜單中的Modify按鈕對(duì)頂點(diǎn)進(jìn)行位移
設(shè)置網(wǎng)格點(diǎn)權(quán)重
我們需要給網(wǎng)格頂點(diǎn)設(shè)置各個(gè)骨骼的權(quán)重,整個(gè)過程如下圖所示:
首先,關(guān)閉Edit Mesh菜單
確認(rèn)勾選的還是手部的貼圖
單擊左下角的Weights按鈕,呼出Weights菜單
單擊Weights菜單底部的Bind按鈕,來綁定骨骼
選擇手部的五根骨骼,直到它們都出現(xiàn)Weights菜單里,注意不同的骨骼顏色是不一樣的
單擊Weights菜單的Auto按鈕或者按`esc`鍵,來觸發(fā)Spine的自動(dòng)權(quán)重計(jì)算
勾選Weights菜單的Overlay,我們可以看到綁定后的權(quán)重?zé)崃D
動(dòng)起來!
現(xiàn)在我們要讓手動(dòng)起來了,我們只展示一個(gè)彎曲手臂的動(dòng)畫即可。
首先,我們需要設(shè)置關(guān)鍵幀,讓我們?cè)诘?幀和第30幀設(shè)置好關(guān)鍵幀,這兩個(gè)關(guān)鍵幀對(duì)應(yīng)的手臂位置是完全一樣的,因?yàn)槲覀冃枰h(huán)播放動(dòng)畫。
具體步驟如下圖:
確保左上角的模式處于ANIMATE模式
選中手部的五根骨骼(按住`cmd`鍵或`control`鍵依次點(diǎn)選)
選中第0幀
單擊Rotate下的鑰匙按鈕,我們對(duì)手臂的旋轉(zhuǎn)屬性設(shè)置關(guān)鍵幀
選擇第30幀
重復(fù)第4步的操作,使第30幀的關(guān)鍵幀與第0幀完全相同
接下來我們只需輕輕旋轉(zhuǎn)手臂,并在0-30幀中間找一個(gè)幀當(dāng)做關(guān)鍵幀即可:我們選擇第15幀作為中間的關(guān)鍵幀。
選擇第15幀
確保Rotate按鈕被選中
向上旋轉(zhuǎn)5根骨骼到一個(gè)角度
按下K幀按鈕進(jìn)行關(guān)鍵幀設(shè)置
按下播放按鈕來預(yù)覽動(dòng)畫
額外的,我給另一只手、嘴巴、臉部和頭發(fā)都做了MESH,以下是動(dòng)畫的效果圖:
2.3.4.3 前端展示骨骼動(dòng)畫
用Spine將制作好的骨骼動(dòng)畫進(jìn)行導(dǎo)出輸出資源(合圖信息文件:atlas;動(dòng)畫信息文件:json,圖片合圖:png),將這些資源交由前端進(jìn)行展示。
前端開發(fā)根據(jù)Spine或者DragonBones能夠支持的渲染引擎,在項(xiàng)目中導(dǎo)入渲染引擎進(jìn)行展示骨骼動(dòng)畫。
2.3.5 3D動(dòng)畫
前端3D動(dòng)畫實(shí)現(xiàn)可以通過perspective屬性操作用CSS 3D來實(shí)現(xiàn),或者直接借助開源的Three.js開源庫(kù)進(jìn)行實(shí)現(xiàn)。
由于3D動(dòng)畫涉及的內(nèi)容較多,篇幅有限,后面我們將專門開一章來講解前端3D動(dòng)畫。
三、現(xiàn)有方案總結(jié)
3.1 純CSS實(shí)現(xiàn)
適合場(chǎng)景:?簡(jiǎn)單的展示型動(dòng)畫
使用transitionanimation屬性,設(shè)置相應(yīng)的關(guān)鍵幀狀態(tài),并且借助一些緩動(dòng)函數(shù)來進(jìn)行實(shí)現(xiàn)一些簡(jiǎn)單化的動(dòng)畫。
優(yōu)點(diǎn):
開發(fā)成本低,不需要導(dǎo)入任何額外的依賴包
?缺點(diǎn)與不足:
只能夠勝任做一些比較簡(jiǎn)單化的動(dòng)畫,無法實(shí)現(xiàn)一些過于負(fù)責(zé)的動(dòng)畫。
3.2 Anime.js
適用場(chǎng)景:?簡(jiǎn)單的展示型動(dòng)畫+弱交互型動(dòng)畫
Anime.js是一個(gè)輕量級(jí)的js驅(qū)動(dòng)的動(dòng)畫庫(kù),主要的功能有:
支持keyframes,連接多個(gè)動(dòng)畫
支持Timeline,為實(shí)現(xiàn)更為復(fù)雜的動(dòng)畫提供了可能
支持動(dòng)畫狀態(tài)的控制playback control,播放,暫停,重新啟動(dòng),搜索動(dòng)畫或時(shí)間線。
支持動(dòng)畫狀態(tài)的callback,在動(dòng)畫開始,執(zhí)行中,結(jié)束時(shí)提供回調(diào)函數(shù)
支持SVG動(dòng)畫
可以自定義貝塞爾曲線
任何包含數(shù)值的DOM屬性都可以設(shè)置動(dòng)畫
GitHub:
https://github.com/juliangarn...
codepen倉(cāng)庫(kù):
https://codepen.io/collection...
文檔演示:
http://animejs.com/documentat...
功能介紹:
一定程度上,anime.js也是一個(gè)CSS3動(dòng)畫庫(kù),適用所有的CSS屬性,并且實(shí)現(xiàn)的@keyframes能更方便的實(shí)現(xiàn)幀動(dòng)畫,替代CSS3復(fù)雜的定義方式。使用對(duì)象數(shù)組的形式定義每一幀。
戳我:keyframes實(shí)例
anime({ targets: 'div', translateX: [ { value: 250, duration: 1000, delay: 500, elasticity: 0 }, //第一幀 { value: 0, duration: 1000, delay: 500, elasticity: 0 } //第二幀 ] }) //這個(gè)例子實(shí)現(xiàn)了目標(biāo)元素在兩幀中實(shí)現(xiàn)水平位移
提供的Timeline能實(shí)現(xiàn)更為復(fù)雜的動(dòng)畫效果,通過這個(gè)Timeline,我們可以維護(hù)不同的動(dòng)畫之間的關(guān)系,進(jìn)而通過多個(gè)不同的動(dòng)畫組成一個(gè)更為復(fù)雜的動(dòng)畫。
戳我:Timeline實(shí)例
var myTimeline = anime.timeline(); //通過.add()方法添加動(dòng)畫 myTimeline .add({ targets: '.square', translateX: 250 }) .add({ targets: '.circle', translateX: 250 }) .add({ targets: '.triangle', translateX: 250 });
動(dòng)畫播放的控制,常見的有暫停,重播,繼續(xù),動(dòng)畫狀態(tài)的跟蹤,自動(dòng)播放,循環(huán)次數(shù),抖動(dòng)效果
戳我:playback controls實(shí)例
為動(dòng)畫提供了回調(diào)函數(shù),在動(dòng)畫或時(shí)間線完成的開始,期間或之時(shí)執(zhí)行回調(diào)函數(shù)。
戳我:callback實(shí)例
var myAnimation = anime({ targets: '#begin .el', translateX: 250, delay: 1000, begin: function(anim) { // callback console.log(anim.began); // true after 1000ms } });
支持promise,動(dòng)畫結(jié)束后,調(diào)用anime.finished會(huì)返回一個(gè)promise對(duì)象。
戳我:promise實(shí)例
支持svg繪制路徑,目前不支持canvas繪制。
戳我:SVG實(shí)例
對(duì)于input這樣帶有數(shù)值的元素標(biāo)簽,也可以通過anime實(shí)例來設(shè)置動(dòng)畫。
戳我:DOM ATTRIBUTES實(shí)例
anime({ targets: input, value: 1000, // Animate the input value to 1000 round: 1 // Remove decimals by rounding the value });
優(yōu)點(diǎn):
顯而易見,anime.js不僅實(shí)現(xiàn)了CSS3動(dòng)畫的深度封裝,更多的是通過js驅(qū)動(dòng)來實(shí)現(xiàn)操作動(dòng)畫的狀態(tài),timeline實(shí)現(xiàn)了對(duì)于多個(gè)分支動(dòng)畫的管理,對(duì)于實(shí)現(xiàn)更為復(fù)雜的動(dòng)畫提供了可能。
通過anime.js提供的playback controls和callback,同時(shí)對(duì)于promise的支持,讓我們對(duì)于動(dòng)畫的簡(jiǎn)單交互有了操作的空間。
雖然不支持canvas,但是支持svg繪制路徑。
瀏覽器兼容性比較好,Android 4以上全部支持。
缺點(diǎn):
Anime.js做展示型動(dòng)畫是可以勝任的,但是對(duì)于特別復(fù)雜的動(dòng)畫也是不太能夠?qū)崿F(xiàn),在做交互性動(dòng)畫方面還是需要看場(chǎng)景,它更多適合做一些小型的交互動(dòng)畫,類似于通過觸摸屏幕踢足球這種強(qiáng)交互的,anime.js就不是很有優(yōu)勢(shì)了。
3.3? Lottie
適用場(chǎng)景:?復(fù)雜的展示型動(dòng)畫
通過 AE 上的 Bodymovin 插件將 AE 中制作好的動(dòng)畫導(dǎo)出成一個(gè) json 文件,通過Lottie對(duì)JSON進(jìn)行解析,最后以SVG/canvas/html的方式渲染動(dòng)畫。
能夠完好的展示設(shè)計(jì)師設(shè)計(jì)的各種各樣復(fù)雜的動(dòng)畫。
官方文檔:
http://airbnb.io/lottie/
codepen倉(cāng)庫(kù):
https://codepen.io/collection...
優(yōu)點(diǎn):
跨平臺(tái),一次繪制、一次轉(zhuǎn)換、隨處可用。
文件更小,獲取AE導(dǎo)出的JSON,最后通過lottie渲染為canvas/svg/html格式。
可以通過api操縱動(dòng)畫的一些屬性,比如動(dòng)畫速度;添加動(dòng)畫各個(gè)狀態(tài)的回調(diào)函數(shù)。
動(dòng)畫都是在After Effects中創(chuàng)建的,使用Bodymovin導(dǎo)出,并且本機(jī)渲染無需額外的工程工作。
解放前端工程師的生產(chǎn)力,提高設(shè)計(jì)師做動(dòng)效的自由度。
缺點(diǎn):
Bodymovin 插件待完善,仍然有部分 AE 效果無法成功導(dǎo)出。
對(duì)于交互方面支持的還不是很好,更多的是用來展示動(dòng)畫。
Lottie 對(duì) json 文件的支持待完善,目前有部分能成功導(dǎo)出成 json 文件的效果在移動(dòng)端上無法很好的展現(xiàn)。
很多AE的效果是不支持的?查看支持的特性:Supported Features。
3.4 PixiJs
適用場(chǎng)景:?交互型動(dòng)畫,動(dòng)畫小游戲
PixiJS是一個(gè)2D 渲染引擎, Pixi 主要負(fù)責(zé)渲染畫面。可以創(chuàng)建豐富的交互式圖形,動(dòng)畫和游戲,而無需深入了解WebGL API或處理瀏覽器和設(shè)備兼容性的問題。與此同時(shí),PixiJS具有完整的WebGL支持,如果需要,可以無縫地回退到HTML5的canvas。PixiJs默認(rèn)使用WebGL渲染,也可以通過聲明指定canvas渲染,WebGL在移動(dòng)端Android 4.4 browser并不支持,不過可以使用canvas優(yōu)雅降級(jí)。
Github:?https://github.com/pixijs/pix...
官方文檔:http://pixijs.download/releas...
官方網(wǎng)站:http://www.pixijs.com/
Examples:https://pixijs.io/examples/#/...
特性(摘自官方DOCS):
支持WebGL渲染
支持canvas?渲染(官方稱PixiJS在canvas渲染方面現(xiàn)在是最快的)
非常簡(jiǎn)單易用的API
豐富的交互事件,比如完整的鼠標(biāo)和移動(dòng)端的觸控事件
Pixi使用和?canvas?Drawing幾乎一致的 api,但不同于?canvas?的繪畫 api,使用 Pixi 繪制的圖形是通過?WebGL?在?GPU?上渲染
還有一系列特性需要在學(xué)習(xí)PixiJs之后了解
優(yōu)點(diǎn):
最大優(yōu)勢(shì)莫過于通過WebGL來調(diào)用GPU渲染動(dòng)畫,這樣極大的提升了性能。
無需深入了解WebGL API或者是瀏覽器兼容性(因?yàn)橄旅孢@條原因)。
支持canvas回退,當(dāng)前設(shè)備不支持WebGL時(shí),PixiJs會(huì)使用canvas渲染動(dòng)畫。
完整的DOCS,比較活躍的社區(qū),有利于深入的學(xué)習(xí)。不過我感覺PixiJs學(xué)習(xí)成本相對(duì)來說還是很高的。
缺點(diǎn):
首先是兼容的問題,WebGL在Android 4.4 是不支持的,只能使用canvas進(jìn)行降級(jí)。
Pixi 主要負(fù)責(zé)渲染畫面,很多其它功能開發(fā)者得自己寫或搭配其它庫(kù)來使用,不過按照目前來看,是滿足我們的需求的。
性能:
對(duì)于手機(jī)版本Android4.4 以上的手機(jī),除了代碼層面造成的性能不足,通過WebGL調(diào)用GPU渲染,性能還是有保障的。然而對(duì)于Android4.4只能使用canvas渲染,性能還是要看動(dòng)畫的復(fù)雜度,以及代碼的優(yōu)化
3.5 總結(jié)
簡(jiǎn)單的展示型動(dòng)畫:
對(duì)于比較簡(jiǎn)單的動(dòng)畫,我們可以先嘗試使用原生CSS的transitionanimation屬性來進(jìn)行實(shí)現(xiàn)。
簡(jiǎn)單的展示型動(dòng)畫+弱交互:
對(duì)于簡(jiǎn)單的動(dòng)畫展示并且需要有簡(jiǎn)單的交互行為,比如用戶點(diǎn)擊一下暫停執(zhí)行相應(yīng)操作,待操作完成繼續(xù)播放動(dòng)畫,交互方面比較偏弱,可以采用Anime.js的方案。
Anime.js不僅僅支持所有的CSS屬性,而且可以通過Timeline,callback, playback controls來控制動(dòng)畫執(zhí)行的各個(gè)狀態(tài),并且Anime.js可以配合實(shí)現(xiàn)SVG動(dòng)畫。
復(fù)雜的展示型動(dòng)畫:
如果所需的資源很小,可以先考慮使用GIF動(dòng)圖或者逐幀動(dòng)畫CSS實(shí)現(xiàn);
如果所需的資源較大,可以使用Lottie方案,然后設(shè)計(jì)同學(xué)用AE到處動(dòng)畫json,將動(dòng)畫還原為svg/canvas/html。
強(qiáng)交互&互動(dòng)小游戲&骨骼動(dòng)畫:
對(duì)于交互場(chǎng)景比較負(fù)責(zé)或者需要做一個(gè)小游戲,可以采用PixiJs,通過WebGL來渲染,利用硬件資源,極大的提升性能,在兼容性方面,對(duì)于不支持WebGL的瀏覽器,可以使用canvas渲染來平穩(wěn)回退;
如果是需要展示骨骼動(dòng)畫,可以通過PixiJs方案進(jìn)行渲染由Spine或DragonBones輸出的文件。
編輯:黃飛
評(píng)論
查看更多