1. Lottie是什么?
Airbnb 開源的跨平臺動畫庫,適用于 iOS、Android、React Native 和 Web 等平臺,它可以解析使用 Bodymovin 導(dǎo)出為 json 的 Adobe After Effects 動畫,允許應(yīng)用程序像使用靜態(tài)圖像一樣輕松使用動畫

2. 如何使用?
2.1 基本用法
lottie-android 有兩種引入方式:
1. xml方式
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_rawRes="@raw/hello_world"
// or
app:lottie_fileName="hello_world.json"
// Loop indefinitely
app:lottie_loop="true"
// Start playing as soon as the animation is loaded
app:lottie_autoPlay="true" />
2. 編程方式
LottieAnimationView animationView = ...
animationView.setAnimation(R.raw.hello_world);
// or
animationView.setAnimation(R.raw.hello_world.json);
animationView.playAnimation();
2.2 更多API
lottie 提供了多種對動畫的操作:
playAnimation() //播放動畫
pauseAnimation() //暫停動畫
setMinFrame() //設(shè)置起始幀
setMaxFrame() //設(shè)置結(jié)束幀
setRepeatCount() //設(shè)置重復(fù)次數(shù)
setSpeed() //設(shè)置播放速度
此外,lottie 也提供一系列監(jiān)聽:
addAnimatorListener() //start、end、cancel、repeat回調(diào)
addAnimatorUpdateListener() //update回調(diào)
其他平臺及用法參考官方文檔
3. Lottie實現(xiàn)原理?
3.1 整體關(guān)系圖

從上面不難看出,主要有 3 個橋梁對象:
- LottieAnimationView:門面對象,對外暴露統(tǒng)一的調(diào)用接口,我們通過它輕松實現(xiàn)各種動畫效果
- LottieComposition:負(fù)責(zé)解析 json 描述文件,把 json 內(nèi)容轉(zhuǎn)成 Java 數(shù)據(jù)對象
- LottieDrawable:負(fù)責(zé)繪制,把 LottieComposition 轉(zhuǎn)成的數(shù)據(jù)對象繪制成 Drawable 并顯示到 View 上
LottieComposition 及其往左是數(shù)據(jù)側(cè)。AE 動畫的組成和 PS 很相似,整個動畫用一個 LottieComposition 對象來承裝,一個動畫又包含了若干個圖層 Layer,在圖層上我們可以進(jìn)行一些操作 AnimatableTransform,圖上的 o r p a s 分別表示 5 種變換 opacity、rotate、position、anchor、scale
這里還有一個概念叫關(guān)鍵幀,我們都知道動畫的單位是幀,動畫運行的本質(zhì)就是微分,即預(yù)先設(shè)定初始值和目標(biāo)值,在一段時間內(nèi)不斷改變這個值向目標(biāo)靠近,這個初始值和目標(biāo)值就可以認(rèn)為是關(guān)鍵幀,當(dāng)然在這之間也是能夠插入多個關(guān)鍵值的,這樣就會有多個關(guān)鍵幀了
LottieDrawable 及其往右是渲染側(cè)。數(shù)據(jù)側(cè)的對象只是存儲了數(shù)據(jù),Lottie 會將這些數(shù)據(jù)轉(zhuǎn)換成具備渲染能力的對象,這里他們是有對應(yīng)關(guān)系的,如:CompositionLayer 和 LottieComposition,BaseLayer 和 Layer,TransformKeyframeAnimation 和 AnimatableTransform,KeyframeAnimation 和 Keyframe,而 LottieDrawle 就是一張畫布,它擁有一個 Canvas,當(dāng)我們開始播放動畫,這些圖層便一層一層的在 Canvas 上進(jìn)行繪制,隨著時間(progress)的推進(jìn),各圖層不斷根據(jù)當(dāng)前進(jìn)度計算新的狀態(tài)值,并重復(fù)繪制過程,圖像便動了起來
3.2 主線運行流程
1. json文件內(nèi)容
動畫的數(shù)據(jù)模型從 AE 到我們代碼中會經(jīng)歷如下幾個變化:


從上面可以看出,動畫的數(shù)據(jù)模型中總有下面的包含關(guān)系:

這里再借用一張圖,看看 json 文件中都描述了些什么內(nèi)容:

上圖一些關(guān)鍵項后面都帶了解釋。這里第一部分是 json 文件的外層結(jié)構(gòu),主要是 layers 這個數(shù)組包含了所有的圖層信息,layers 中的 ks 中包含了所有的變換信息,也就是上面一直提到的 o r p a s 變換
2. 動畫運行流程
知道了 json 內(nèi)容的含義,接下來再來看看動畫是怎么運行的,下面是 Lottie 的運行流程圖:

整個的執(zhí)行邏輯大致是這樣的:
- 通過 Factory.fromJsonSync 將 json 文件解析成為 LottieComposition
- 根據(jù) LottieComposition 中的數(shù)據(jù)來構(gòu)造具備渲染能力的 CompositionLayer
- 啟動 ValueAnimator 去不斷監(jiān)聽動畫進(jìn)度,一旦進(jìn)度改變就回調(diào)更新函數(shù)
- 各個圖層根據(jù)當(dāng)前進(jìn)度(progress)計算自身新的狀態(tài)
- LottieDrawable 將它持有的 Canvas 傳給各圖層進(jìn)行繪制,最終顯示到 View 上
4. Lottie Q&A?
4.1 與其他加載方式的比較
- 視圖動畫。 無法真正改變 view 的屬性,只有視覺上的效果
- 屬性動畫。 難以完成設(shè)計師給出的一些精美復(fù)雜的動畫效果
- gif 視頻。 體積是 json 的兩倍以上,存在交互障礙,并且以固定大小渲染,無法按比例放大以匹配大型和高密度屏幕
- png 序列。 需要大量的圖片素材,文件大小通常是 json 大小的 30-50 倍,動畫播放時會占用很多內(nèi)存,也無法按比例放大
- Lottie優(yōu)點如下:
- 100% 還原設(shè)計師給出的各種復(fù)雜動畫效果
- 簡單的實現(xiàn)、控制動畫的播放,開發(fā)效率大大提高
- 可動態(tài)配置下發(fā),實時替換動畫效果
- Lottie性能問題:
- Mask 和 mattes(蒙板和遮罩)對動畫性能會有較大影響,不宜在列表中使用包含 mask 或 mattes 的動畫
- 列表中使用動畫,要使用緩存 LottieAnimationView.setAnimation(String, CacheStrategy),避免內(nèi)存抖動
- Lottie 中 ImageLayer 對圖片的解碼是在主線程的,并且沒有對 Bitmap 重用,可以自己將圖片解碼的邏輯遷移到子線程,并增加對 Bitmap 的緩存來提高性能
4.2 Lottie的使用場景
- Lottie 不適用的兩種場景:
- 給 View 本身添加動畫(如:從右下角到移動到頁面中,并逐漸放大的過渡效果)
- 動畫中有動態(tài)內(nèi)容(如:需要顯示一個數(shù)量,多少來自數(shù)據(jù)庫/網(wǎng)絡(luò))
- Lottie 非常適合像一段動畫的播放這樣的場景使用:
- json 文件的大小比 gif 文件小很多
- 能夠非常方便的控制動畫播放,如:速率、范圍