Lottie 淺析

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,它同樣支持centerCropcenterInside兩個屬性
  • Scaling Up/Down: LottieAnimationViewLottieDrawable都有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負責繪製邏輯
  1. 如何解析json文件
  2. 如何渲染json文件
  3. 動畫播放

解析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());
    }
  }
});

在這裏插入圖片描述

優缺點

優點

  1. 跨平臺,同一份json文件可以同時在iOS和Android上運行
  2. 不需要Native工程師製作動畫,提高效率,並且更加精美的動畫
  3. 動態替換,不僅支持本地json,zip文件而且支持url遠端拉去數據
  4. 相比較webp、gif動畫,json的文件更小
  5. 輕量級sdk

缺點

  1. Masks 和 mattes會有較大的性能問題,並且蒙層/遮罩的交集成比例上升,如果開啓硬件加速,可能會有幾倍的性能提升
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章