本文主要介紹了動畫的原理相關(guān)概念梁厉,對其他平臺的動畫做了一個(gè)簡要的梳理敏储,并簡要的介紹了Flutter動畫的一些知識。
1. 動畫介紹
動畫對于App來說,非常的重要佳鳖。很多App,正是因?yàn)橛辛藙赢嫲碧剩圆艜X得炫酷萤彩。移動端的動畫庫有非常的多,例如iOS上的Pop坚弱、web端的animate.css蜀备、Android端的AndroidViewAnimations、跨平臺的Lottie等荒叶。正是因?yàn)橛辛诉@些封裝好的動畫庫碾阁,我們制作酷炫的效果方便了不少。當(dāng)然了些楣,這些庫都是基于各平臺基礎(chǔ)的動畫API實(shí)現(xiàn)的脂凶,筆者今天要聊的,也就是基礎(chǔ)的動畫及背后的原理愁茁。
1.1 動畫的本質(zhì)
動畫顧名思義蚕钦,就是動起來的畫面。畫面為什么會動起來了呢鹅很?在回答這個(gè)問題之前嘶居,我們先引入一個(gè)概念。
人眼在觀察景物時(shí)促煮,光信號傳入大腦神經(jīng)食听,需經(jīng)過一段短暫的時(shí)間,光的作用結(jié)束后污茵,視覺形象并不立即消失樱报,這種殘留的視覺稱“后像”,視覺的這一現(xiàn)象則被稱為“視覺暫留”泞当。
視覺暫留被認(rèn)為是電影的最重要的一個(gè)理論基礎(chǔ)迹蛤。我們看到的動畫,實(shí)際上是一連串的畫面組成,只不過是以很快的速度去播放盗飒,人眼在下一個(gè)畫面出來之前嚷量,還殘留著上一個(gè)畫面的視覺,看起來就像是在沒有間隔的播放這一系列的圖片逆趣,也就是我們稱之為的動畫蝶溶。
1.2 相關(guān)概念
動畫會有很多相關(guān)的概念,理解了這些概念宣渗,會對實(shí)際的使用更有幫助抖所。
1.2.1 幀
剛才在介紹動畫本質(zhì)的時(shí)候,用到了畫面這個(gè)詞匯痕囱,只是方便讀者去理解田轧,這個(gè)畫面,在學(xué)術(shù)上叫做幀
鞍恢。
幀就是影像動畫中最小單位的單幅影像畫面傻粘,一幀就是一副靜止的畫面。
幀里面又分為關(guān)鍵幀和過渡幀帮掉,這兩概念是理解一些動畫的基礎(chǔ)弦悉,例如Android中的補(bǔ)間動畫。在一些場景中蟆炊,我們可能不會給出一個(gè)動畫的所有幀稽莉,所以將幀分成關(guān)鍵幀和過渡幀。關(guān)鍵幀可以理解為一個(gè)動畫的起始狀態(tài)盅称,而過渡幀則是系統(tǒng)自動完成插在關(guān)鍵幀之間的部分肩祥。
我們知道Android中的補(bǔ)間動畫后室,基礎(chǔ)的有四種類型缩膝,平移、縮放岸霹、旋轉(zhuǎn)疾层、透明度。而我們設(shè)置動畫的時(shí)候贡避,通常只是設(shè)置起始的狀態(tài)痛黎,也就是關(guān)鍵幀,中間過程其實(shí)我們并不需要去考慮刮吧,如果關(guān)注動畫速率的話湖饱,頂多加一個(gè)差值器去控制,但是中間生成的幀我們并沒有提供杀捻。
系統(tǒng)為什么能夠補(bǔ)齊過渡幀呢井厌?我們看下這四種基本的動畫類型,給定起始狀態(tài),中間狀態(tài)我們其實(shí)是可以通過計(jì)算推演出來的仅仆,這也是系統(tǒng)為什么能夠補(bǔ)齊的原因器赞。
是不是只有這四種才可以通過系統(tǒng)填補(bǔ)過渡幀呢?顯然不是的墓拜,例如一個(gè)跳躍前進(jìn)的動畫港柜,添加一些限制條件,就可以推演出中間的狀態(tài)咳榜。系統(tǒng)提供的只是比較常見的四種夏醉,并不是說只有這四種,而是絕大部分動畫都可以通過這四種組合實(shí)現(xiàn)贿衍。當(dāng)然了授舟,肯定也是有實(shí)現(xiàn)不了的,這個(gè)時(shí)候有一個(gè)辦法就是通過canvas畫出來贸辈。
另外再插一嘴释树,Android系統(tǒng)提供的四種動畫操作,也是變換矩陣是四維的原因擎淤,具體的就不多說了奢啥,之前文章也有介紹過。
最后一嘴嘴拢,此處講解幀的概念桩盲,拿了很多Android相關(guān)的知識去講解,只是希望讀者能夠通過一些已知的概念席吴,去理解一些未知的赌结。動畫的原理都一樣,具體到某個(gè)平臺孝冒,可能頂多就是實(shí)現(xiàn)或者叫法不一樣罷了柬姚。
1.2.2 幀數(shù)與FPS
小時(shí)候很多人都玩過書角動畫。在書或者本子的一角庄涡,每一頁都畫上一個(gè)畫面量承,然后撥書角,不同速度撥穴店,動畫的感受不一樣撕捍,撥的越快,動畫越流暢泣洞。這是為什么呢忧风?這就牽扯到幀數(shù)與FPS了。
幀數(shù)球凰,幀的數(shù)量狮腿。FPS(Frame per Second)该窗,即每秒顯示幀數(shù)。
這兩個(gè)概念蚤霞,主要是FPS有什么作用呢酗失?這是因?yàn)槿搜凵順?gòu)造的原因。人眼殘留鏡像的時(shí)間是有限的昧绣,如果過了這個(gè)時(shí)間规肴,下一幀還沒有變化,就會感覺不流暢夜畴。但也不是幀數(shù)越大越好拖刃,畢竟人眼也是有極限的。
1.2.3 插值器
如果動畫播放一直都是這種勻速的進(jìn)行贪绘,那表現(xiàn)形式就太單一了兑牡。那如何實(shí)現(xiàn)非線性的動畫效果呢,這個(gè)時(shí)候就需要用到插值器了税灌。
插值器其實(shí)并不復(fù)雜均函,就是一個(gè)數(shù)學(xué)函數(shù),設(shè)置屬性值從初始值過渡到結(jié)束值的變化規(guī)律菱涤。每個(gè)平臺都有自己定義好的一系列插值器苞也,可以供開發(fā)者選擇使用,也提供自定義的接口粘秆,本質(zhì)上是一個(gè)貝塞爾函數(shù)如迟。
一個(gè)勻速插值器如下:
屬性值百分比 = 時(shí)間百分比
1.3 如何實(shí)現(xiàn)
動畫的基本原理和一些基本概念都介紹了一下,現(xiàn)在來聊一下動畫的實(shí)現(xiàn)攻走。
先拋開系統(tǒng)層級的各種渲染優(yōu)化殷勘,也僅僅是以補(bǔ)間動畫為例,假設(shè)以現(xiàn)有的移動平臺基礎(chǔ)上昔搂,去實(shí)現(xiàn)一套簡單的動畫框架玲销,該如何去實(shí)現(xiàn)呢?
以Android的為例巩趁,要實(shí)現(xiàn)平移痒玩、縮放淳附、旋轉(zhuǎn)议慰、透明度這四種基礎(chǔ)的補(bǔ)間動畫,可以看到奴曙,這些都是基于某個(gè)屬性的動畫别凹,平移是基于point、縮放是基于scale洽糟、旋轉(zhuǎn)是基于angle炉菲、透明度是基于alpha堕战。
結(jié)合插值器,提煉出一個(gè)通用的動畫類拍霜,這個(gè)類的作用是根據(jù)插值器嘱丢,得到視圖某個(gè)時(shí)間點(diǎn)的屬性變化的狀態(tài)。
既然各個(gè)時(shí)間點(diǎn)的狀態(tài)已經(jīng)有了祠饺,剩下來的就是讓各個(gè)狀態(tài)渲染出來越驻。底層的機(jī)制在此處不去討論,這個(gè)地方就需要一個(gè)定時(shí)器道偷,定時(shí)器的作用是每隔一段時(shí)間就把素材渲染到屏幕上缀旁。
至此,一個(gè)簡易的動畫框架就出來了勺鸦。如果對各平臺比較了解的話并巍,就知道我說的是視圖動畫,真正的動畫引擎不是這么簡單换途,涉及到的技術(shù)也比較復(fù)雜懊渡,但是大體的思想不會有錯(cuò),不管是哪種動畫军拟,都是跟時(shí)間相關(guān)的幀序列距贷,只是實(shí)現(xiàn)方式不同。
這也是筆者為什么花這么多篇幅去介紹動畫相關(guān)的概念吻谋,知道一些底層原理后忠蝗,不管什么平臺,怎么去實(shí)現(xiàn)漓拾,底層的思想肯定都差不多阁最,只是實(shí)現(xiàn)上的不同。
2. 其他平臺的動畫
Flutter動畫骇两,與Android速种、iOS等平臺對比,其實(shí)本身并沒有什么特別之處低千∨湔螅基本的原理是一樣的,只是提供的種類以及實(shí)現(xiàn)的方式不同罷了示血。
2.1 Android動畫
Android的動畫棋傍,大的分類有兩種:
- 視圖動畫(View Animation)
- 屬性動畫(Property Animation)
視圖動畫又可以分為兩類:
- 補(bǔ)間動畫(Tween Animation)
- 逐幀動畫(Frame Animation)
這之間的差別是什么呢?它們只有實(shí)現(xiàn)上的差別
- 補(bǔ)間動畫是根據(jù)初始狀態(tài)难审,系統(tǒng)自動補(bǔ)充中間狀態(tài)瘫拣;
- 逐幀動畫則是需要我們提供每一幀;
- 視圖動畫只是作用于視圖上告喊,而不會改變控件的屬性麸拄;
- 屬性動畫則是會實(shí)實(shí)在在的更改控件的屬性派昧。
可以看出Android的動畫分類還是比較明晰的。
2.2 iOS動畫
iOS很久沒弄了拢切,在這里也簡單說下蒂萎,不對的話還請各位指正。
- 隱式動畫
- 顯式動畫
顯式動畫又可以分為兩類:
- 基礎(chǔ)動畫
- 關(guān)鍵幀動畫
這些動畫類別之間的差別是什么呢淮椰?
- 隱式動畫岖是,顧名思義是不指定動畫類型,更改某個(gè)屬性实苞,Core Animation來決定如何且何時(shí)去做動畫豺撑;
- 基礎(chǔ)動畫,根據(jù)起始值來做動畫黔牵;
- 關(guān)鍵幀動畫聪轿,則是定義一系列關(guān)鍵幀,系統(tǒng)自動補(bǔ)齊中間的過渡幀猾浦。
通過動畫這一塊兒陆错,可以看出iOS的分類其實(shí)是比較的模糊的,有一些歷史包袱金赦。
2.3 css動畫
css動畫大體上有兩種:
- Transition
- Animation
web中的動畫分類簡單的多了
- Transition動畫音瓷,給定起始值,可以結(jié)合插值器做動畫夹抗;
- Animation動畫绳慎,則是定義一系列關(guān)鍵幀,系統(tǒng)補(bǔ)齊中間的過渡幀漠烧。
2.4 小節(jié)
通過上面?zhèn)€平臺動畫粗略的介紹杏愤,動畫在不同平臺雖然被叫著不同的名稱,本質(zhì)上其實(shí)都差不多的已脓,變來變?nèi)ザ际沁@幾種方式珊楼,要么根據(jù)屬性要么根據(jù)關(guān)鍵幀,要么更改繪制層度液,要么更改控件本身屬性厕宗。一些游戲引擎,雖然我沒有看堕担,但是我覺得原理也大致相似已慢。
3. Flutter動畫
上面鋪墊了這么多,終于到Flutter動畫了照宝。Flutter是一門比較新的技術(shù)蛇受,歷史包袱理應(yīng)說是最小的句葵。
3.1 Flutter動畫分類
Flutter動畫分為兩類:
- 補(bǔ)間動畫(Tween Animation)
- 基于物理的動畫(Physics-based animation)
補(bǔ)間動畫很好理解厕鹃,基于物理的動畫是這個(gè)什么鬼兢仰。
基于物理的動畫是一種遵循物理學(xué)定律的動畫形式
舉個(gè)例子,比方說你滑動一張圖片剂碴,這個(gè)過程不是勻速的把将,而是起始速度快,然后慢慢的降速忆矛,就像一本書在地上往前推一樣察蹲。它有什么特點(diǎn)呢?
- 遵循物理學(xué)定律催训;
- 能夠依據(jù)加速度和速度去計(jì)算和更新每一幀的動畫數(shù)值洽议;
- 當(dāng)受力平衡時(shí),動畫為處于恒定運(yùn)動或靜止?fàn)顟B(tài)漫拭。
哈哈亚兄,最后一點(diǎn)是不是似曾相識,這樣做的好處是什么呢采驻?隨著人們生活水平的極大提升审胚,移動端硬件這些年也是趕英超美,人們不再滿足于簡單的動畫礼旅,于是就有部分有(xian)識(de)之(dan)士(teng)膳叨,實(shí)現(xiàn)了基于物理學(xué)定律的動畫。
這種動畫iOS或者Android有沒有呢痘系,是有的菲嘴,但不是作為最基礎(chǔ)的動畫API被提供。為什么其他平臺沒有將這個(gè)納入最基本的動畫中去呢临谱?
- 歷史原因。iOS以及Android端多年前就誕生了奴璃,那個(gè)時(shí)候悉默,硬件資源都是極其有限的,當(dāng)時(shí)的環(huán)境不足以支撐這種動畫效果苟穆。但也不是說沒有抄课,一些游戲引擎里面也是有的,但是作為操作系統(tǒng)雳旅,把這些集成進(jìn)去跟磨,還是不太現(xiàn)實(shí)的。
- 認(rèn)知過程攒盈。電腦以及移動端這些年的發(fā)展抵拘,最開始只是滿足于查看最簡單的文本,然后各種圖片視頻型豁。隨著互聯(lián)網(wǎng)的越來越普及僵蛛,人們的需求越來越多了尚蝌。于是,在一些游戲里面才會見到的基于物理學(xué)定律的動畫充尉,進(jìn)入了尋常百姓家飘言。反觀一下,現(xiàn)在也是有非常多的“委屈”事物驼侠。例如人類幾千年都是通過人眼看現(xiàn)實(shí)的事物姿鸿,現(xiàn)在卻被限制在一個(gè)小屏幕上,這其實(shí)是不合理的倒源。所以AR苛预、VR,還有一些動畫片科幻片中的遠(yuǎn)程感知等技術(shù)笋熬,才會層出不窮碟渺,當(dāng)然這個(gè)扯的有些遠(yuǎn)了。
基于物理的動畫這么好突诬,那有什么好處呢苫拍?更自然,更加符合人們的認(rèn)知旺隙。
3.2 分類的原因
前面講的各平臺的動畫绒极,從本質(zhì)上看,基于某個(gè)屬性也好蔬捷,幀動畫也好垄提,都是從一種狀態(tài)到另一種狀態(tài),而中間過程是可以推演出來的周拐,所以Flutter提供補(bǔ)間動畫铡俐。
基于物理的動畫,我猜測可能是為了實(shí)現(xiàn)其他平臺上的一些效果妥粟,例如彈簧审丘、阻尼效果等等。所以Flutter就提供了這種動畫API勾给,畢竟沒什么包袱滩报。
3.3 動畫模式
Flutter提煉了三種動畫模式,與其說提煉出來的播急,倒不如說統(tǒng)一不能更為合適脓钾。
- list、grid中的動畫(Animated list or grid)桩警。場景是item的添加或者刪除操作可训;
- 轉(zhuǎn)場動畫(Shared element transition)。場景是當(dāng)前頁面打開另一頁面的過渡動畫;
- 交錯(cuò)動畫(Staggered animation)握截。場景是需要部分或者完全交錯(cuò)的動畫飞崖。
3.4 復(fù)雜度
Flutter的實(shí)現(xiàn)原理以及這個(gè)階段,注定了做動畫是非常麻煩的一件事情川蒙⊙晾鳎跨平臺的技術(shù)做動畫都麻煩长已,這個(gè)似乎是通識畜眨,為了跨平臺而同化的一些東西,到異化部分术瓮,就變得蛋疼了康聂,動畫正是這種存在。
Flutter做動畫復(fù)雜提現(xiàn)在哪些地方呢胞四?
- 實(shí)現(xiàn)的動畫較少恬汁,這個(gè)是初期,沒啥好說的辜伟;
- 動畫實(shí)現(xiàn)的方式復(fù)雜氓侧,這個(gè)是Flutter的設(shè)計(jì)思想所決定的。
4. 小節(jié)
關(guān)于動畫的具體的實(shí)現(xiàn)导狡、一些底層的代碼邏輯以及如何使用约巷,將會在下一篇文章中做介紹。這篇文章更多的是偏于一些普適性的介紹旱捧,關(guān)于Flutter動畫相關(guān)的介紹反而很少独郎。希望讀者能夠了解一些動畫的原理,以及各個(gè)平臺動畫的大致實(shí)現(xiàn)方式枚赡,這樣可以更好的理解Flutter動畫的設(shè)計(jì)思想氓癌。文中若有錯(cuò)誤的地方,還懇請指出贫橙,在此不勝感激贪婉。
5. 后話
筆者建了一個(gè)Flutter學(xué)習(xí)相關(guān)的項(xiàng)目,Github地址卢肃,里面包含了筆者寫的關(guān)于Flutter學(xué)習(xí)相關(guān)的一些文章谓松,會定期更新,也會上傳一些學(xué)習(xí)Demo践剂,歡迎大家關(guān)注鬼譬。