天天看點

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

從json檔案到炫酷動畫-Lottie實作思路和源碼分析,Lottie是最近Airbnb開源的動畫項目,支援Android、iOS、ReactNaitve三個平台,本文分析主要Lottie把json檔案轉為動畫的思路和源碼實作。

文章首先介紹Lottie的基本使用,然後分析把json檔案映射到動畫的實作思路,最後分析Lottie的源碼實作,這裡分析的是Lottie-Android。

基本用法

與使用相關的隻有三個類檔案: LottieAnimationView、LottieComposition、LottieDrawable ,是以Lottie使用起來特别簡單(需要注意Lottie支援API16及以上)。

最簡單的使用方式是在xml中增加LottieAnimationView:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

"Logo/LogoSmall.json"是需要加載的動畫資料路徑,根目錄是assets目錄。

也可以通過代碼設定動畫資料json路徑:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

然後在代碼中控制動畫播放或者添加監聽事件:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

Lottie提供了LottieDrawable可以使用:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

可以看到Lottie使用起來非常簡單,我們之後就從以上用到的 LottieAnimationView、LottieComposition、LottieDrawable 入手來分析下Lottie動畫的實作原理。

思路分析

我們先從底層思考下如何在螢幕上繪制動畫,最簡單的方式是把動畫分為多張圖檔,然後通過周期替換螢幕上繪制的圖檔來形成動畫,這種暴力的方式非常簡單,但缺點明顯,很耗記憶體,動畫播放中前後兩張替換的圖檔在很多元素并沒有變化,重複的内容浪費了空間。

為了提高空間使用率,可以把圖檔中的元素進行拆分,使用過photoshop的同學知道,其實在處理一張圖檔時,可以把一張複雜的圖檔使用多個圖層來表示,每個圖層上展示一部分内容,圖層中的内容也可以拆分為多個元素。拆分元素之後,根據動畫需求,可以單獨對圖層,甚至圖層中的元素設定平移、旋轉、收縮等動畫。

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

Lottie使用json檔案來作為動畫資料源,json檔案是通過 Bodymovin 插件導出的,檢視sample中給出的json檔案,其實就是把圖檔中的元素進行來拆分,并且描述每個元素的動畫執行路徑和執行時間。Lottie的功能就是讀取這些資料,然後繪制到螢幕上。

現在思考如果我們拿到一份json格式動畫如何展示到螢幕上。首先要解析json,建立資料到對象的映射,然後根據資料對象建立合适的Drawable繪制到View上,動畫的實作可以通過操作讀取到的元素完成。

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

源碼分析

1. json檔案到對象的映射

Lottie使用 LottieComposition 來作為After Effects的資料對象,即把json檔案映射到 LottieComposition , LottieComposition 中提供了解析json的靜态方法:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

我們看下 LottieComposition 都有哪些成員變量,這些成員變量描述了After Effects中的動畫。

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

可以看到startFrame、endFrame、duration、scale等都是動畫中常見的。我們看下 List ,看名字就是映射拆分後的圖層資料:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

Layer 中完成layer的json資料解析:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

2. 資料對象到Drawable的映射

AnimatableLayer 繼承自 Drawable ,我們看下它的子類:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

其中 LayerView 對應着 Layer 資料, Layer 中有

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

對應的 LayerView 中有

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

可以簡單地了解為ViewGroup中可以包含ViewGroup或者View,但其實整個Lottie實作的動畫都是繪制在一個View LottieAnimationView 上。

AnimatableLayer 的其它子類如 ShapeLayer,RectLayouer 等作為 LayerView 中 List 的元素。

3. 繪制

LottieAnimationView 繼承自 AppCompatImageView ,封裝了一些動畫的操作,如:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

具體的繪制時委托為 LottieDrawable 完成的,我們看下 LottieDrawable 中的 draw() 方法:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

LottieDrawable 繼承自 AnimatableLayer ,其 draw() 方法如下:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

可以看到先繪制了本層的内容,然後開始繪制包含的 layers 的内容:

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

這個過程于界面中ViewGroup嵌套繪制類似。

實作分析

上面我們根據動畫繪制的思路分析了下Lottie實作機制,下面從正面來捋一下程式的執行過程:

建立 LottieAnimationView lottieAnimationView

建立 LottieDrawable lottieDrawable

使用 LottieComposition 中的靜态方法解析json檔案建立 LottieComposition lottieComposition ,這個過程中已經建立來多個 Layer 對象。

lottieDrawable.setComposition(lottieComposition)

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

先清理之前的資料,然後開始 buildLayersForComposition ,即根據 lottieComposition 建立多個 layerView ,此時已經建立好了多個Drawable,并通過List建立的為以 lottieDrawable 為根的一個drawable樹。

lottieAnimationView.setImageDrawable(lottieDrawable)lottieAnimationView.playAnimation()

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

直接委托給了 lottieDrawable , lottieDrawable 中有 private final ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

重點看下 setProgress 方法

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

調用了 private final List> animations = new ArrayList<>() 的 setProgress :

android lottie字型json,從json檔案到炫酷動畫-Lottie實作思路和源碼分析

在 onValueChanged 時,各個建立好的Drawable會根據需求進行重繪,達到動畫的效果。

Lottie把動畫從View的動效轉移到了Drawable上。

Lottie的性能

可以看到Lottie把json描述的動畫資料映射到Drawable之後,實作動畫時用到了 ValueAnimator ,在動畫更新時使用Drawable而非View,個人感覺在不需要互動時Drawable顯然比View更加輕量。以下是Lottie性能的官方的說明:

如果沒有mask和mattes,那麼性能和記憶體非常好,沒有bitmap建立,大部分操作都是簡單的cavas繪制。

如果存在mattes,将會建立2~3個bitmap。bitmap在動畫加載到window時被建立,被window删除時回收。是以不宜在RecyclerView中使用包涵mattes或者mask的動畫,否則會引起bitmap抖動。除了記憶體抖動,mattes和mask中必要的bitmap.eraseColor()和canvas.drawBitmap()也會降低動畫性能。對于簡單的動畫,在實際使用時性能不太明顯。

如果在清單中使用動畫,推薦使用緩存LottieAnimationView.setAnimation(String, CacheStrategy) 。

以上就是對于安卓開發方面的知識點簡介,從json檔案到炫酷動畫-Lottie實作思路和源碼分析,更多相關内容請繼續關注拓勝科技安卓技術頻道,或者需要了解拓勝安卓教育訓練方面的問題,可以線上免費咨詢拓勝教育老師。