Lottie 簡介
Lottie是是一個可以解析Adobe After Effects使用BodyMovin插件導出的動畫json文件,並且渲染到手機和網頁上的庫,Lottie支持Android,iOS,Web和Windows。
Lottie Android
如何使用
Lottie在Android僅支持Gradle的形式依賴,需要在你的build.gradle
中添加以下的依賴
dependencies {
...
implementation "com.airbnb.android:lottie:$lottieVersion"
...
}
到目前爲止最新的版本是: 3.1.0
支持的文件類型
Lottie支持API 16以上,也就是android 4.1以上。
src/main/res/raw
目錄下的json動畫文件src/main/assets
目錄下的json動畫文件src/main/assets
目錄下的zip文件- json或者zip的url鏈接
- json字符串,可以是通過網絡請求獲得的。
- json或者zip文件的
InputStream
在XML中如何使用
這是最簡單的方式,推薦使用lottie_rawRes
,因爲你可以通過資源引用來使用靜態的動畫文件。
<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" />
動畫的緩存
所有的Lottie的動畫都默認使用了LRU
緩存機制。這個是2.6.0版本更改的,之前的版本是用Strong/WeakRef實現的。
Animation Listeners
你可以控制動畫或者增加監聽器:
animationView.addAnimatorUpdateListener((animation) -> {
// Do something.
});
animationView.playAnimation();
...
if (animationView.isAnimating()) {
// Do something.
}
...
animationView.setProgress(0.5f);
...
在監聽的代碼中,你可以通過animation.getAnimatedValue()
來獲取當前動畫的進度,不論是否設置了最大/最小的幀[0,1]。animatin.getAnimatedFraction()
將會返回你設置大小的進度。
自定義動畫過程
大部分情況下,直接使用playAnimation()
即可,一些特殊的case,你也可以使用setProgress(...)
來啓動滑動,例如:
// Custom animation speed or duration.
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.addUpdateListener(animation -> {
animationView.setProgress(animation.getAnimatedValue());
});
animator.start();
Looping
Lottie支持重複播放,你可以使用setRepeatMode(...)
或者setRepeatCount(...)
,或者在xml中使用lottie_loop="true"
。
動畫的尺寸(px vs dp)
Lottie將所有的px值轉換爲dp值,這樣就能保證在所有的設備上的大小是一致的。如果你的動畫尺寸不是完美的,你可以有以下兩個選擇:
- Image scaleType:
LottieAnimationView
繼承自ImageView
,它同樣支持centerCrop
和centerInside
兩個屬性 - Scaling Up/Down:
LottieAnimationView
和LottieDrawable
都有setScale(float)
的API函數,PS:如果縮小你的動畫,也可以減少每幀需要繪製的大小,也就是會提升性能。
動態屬性
你可以在運行時動態的更新屬性,這個可以幫你完成很多需求:
- 改變主題(白天或者夜晚的主題)
- 根據時間的相應來做出相應的事件
- 不同的事件執行不同的動畫
Lottie實現原理
基礎概念
圖層
圖層的概念與Photoshop中的圖層概念類似:圖層是對整個動畫進行了更細粒度的區分,將不同的類型元素進行了拆分,將不同的形狀、純色、文本等元素分別分配到不同的圖層中,所有圖層依序疊加在一起構成了所渲染的圖像。在未與其他圖層關聯時,修改某一圖層的屬性不會影響到其他圖層,這樣在執行動畫的時候可以更加清晰的對各個元素執行不同的動畫邏輯。
public enum LayerType {
PRE_COMP,
SOLID,
IMAGE,
NULL,
SHAPE,
TEXT,
UNKNOWN
}
關鍵幀
動畫的單位是幀,預先設定初始值和目標值,在一段時間內不斷改變這個值向目標靠近,這個初始值和目標值就可以認爲是關鍵幀,在這之間可以插入多個關鍵值,這樣就會有多個關鍵幀了。
json
{
"v": "4.10.1", //版本號
"fr": 25, // 幀率
"ip": 0, // 首幀
"op": 106, //尾幀
"w": 1920, //寬
"h": 1080, //高
"nm": "Comp 1", //名稱
"ddd": 0,
"assets": [], //圖片集合
"fonts": {...}, //字體
"layers": [
{
"ddd": 0,
"ind": 1, //圖層id
"ty": 4, //圖層類型index-shape
"nm": "perki Outlines", //圖層name
"sr": 1, //transform
...
原理
核心類:
LottieAnimationView
繼承自AppCompatImageView
,通過它加載展示各種動畫LottieComposition
通過生成LottieCompositionFactory
解析json文件,轉換成Java數據對象LottieDrawable
負責繪製邏輯
- 如何解析json文件
- 如何渲染json文件
- 動畫播放
解析Json文件
渲染動畫
LottieDrawable.draw()
-> CompositionLayer.draw()
-> Layers.draw()
動畫
LottieAnimationView.playAnimation
-> LottieDrawable.playAnimation
-> LottieValueAnimator.playAnimation
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
if (compositionLayer != null) {
compositionLayer.setProgress(animator.getValue());
}
}
});
優缺點
優點
- 跨平臺,同一份json文件可以同時在iOS和Android上運行
- 不需要Native工程師製作動畫,提高效率,並且更加精美的動畫
- 動態替換,不僅支持本地json,zip文件而且支持url遠端拉去數據
- 相比較webp、gif動畫,json的文件更小
- 輕量級sdk
缺點
- Masks 和 mattes會有較大的性能問題,並且蒙層/遮罩的交集成比例上升,如果開啓硬件加速,可能會有幾倍的性能提升