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会有较大的性能问题,并且蒙层/遮罩的交集成比例上升,如果开启硬件加速,可能会有几倍的性能提升