5月27日 18:25

Lottie 动画库的工作原理是什么?

Lottie 是 Airbnb 开源的动画渲染库,核心思路是把 After Effects 动画导出为 JSON,然后在客户端用原生绘图 API 实时渲染——不走 GIF、不走视频,走的是矢量绘制。

设计师在 AE 里做好动画,装一个 Bodymovin 插件点导出,拿到的 JSON 文件直接丢进项目,几行代码就能播动画。JSON 里存的是图层数据、关键帧、路径信息,Lottie 库负责解析这些数据,在 iOS 上用 Core Animation 渲染,Android 上用 Canvas,Web 上用 SVG 或 Canvas。所以同一份动画文件,三端表现一致。

具体来说,渲染过程分三步:先解析 JSON 构建数据模型(Android 上叫 LottieComposition),然后根据当前播放时间用插值算法算出每一帧各属性的中间值,最后把图层按顺序叠加绘制到画布上——类似 PS 的图层叠加原理,底层依赖 Canvas 的 save/restore 机制。

相比 GIF 和视频,Lottie 的优势很明显:文件体积小得多(一个复杂动画可能就几 KB 的 JSON,而同等效果的 GIF 通常要几百 KB),矢量绘制支持无限缩放不失真,而且可以通过代码控制播放进度、速度、暂停,甚至动态修改颜色和文字内容——这些 GIF 做不到。

但 Lottie 不是万能的。它只支持 AE 中的一部分特性,像粒子效果、3D 摄像机、某些混合模式就不支持。动画越复杂,JSON 文件越大,低端设备上解析也会变慢。另外 Lottie 的版本兼容性也是个坑——不同平台的 Lottie 库版本对 JSON 特性的支持程度不一样,设计师在 AE 里用了一个遮罩效果,iOS 能正常渲染,Android 可能就显示异常。

追问

Lottie 和 GIF/MP4 动画有什么区别?

对比项LottieGIFMP4
文件体积极小(KB 级)大(百 KB~MB)较大
缩放矢量,无损位图,模糊位图,模糊
交互控制代码控制播放/暂停/速度仅播放播放/暂停
动态修改支持改颜色/文字不支持不支持
透明背景原生支持需要处理不方便
渲染方式原生矢量绘制位图逐帧硬件解码

Bodymovin 导出的 JSON 文件结构是什么样的?

大致分三层:最外层是动画元信息(版本号、宽高、帧率、inPoint/outPoint 标记起止帧),中间是图层列表(每个图层对应 AE 中的一个图层,包含变换属性、遮罩、效果等),最内层是关键帧数据(每个可动画属性在不同时间点的值,用贝塞尔曲线描述缓动)。渲染时 Lottie 从外到内逐层解析,用插值算法算出当前帧的属性值,再绘制到画布上。

实际项目里用过吗?遇到过什么坑?

踩过两个典型的坑。一是跨平台渲染不一致——设计稿在 LottieFiles 预览看着正常,跑在低端 Android 机上遮罩就出问题了,后来发现是那个 Android Lottie 版本不支持该遮罩类型,降级 AE 效果才解决。二是 JSON 文件体积——有个动画导出来 200KB+,首屏加载就卡了一下,后来用 Lottie 的缓存策略预加载才缓解。所以实际项目中一定要在目标设备上测试渲染效果,别只在预览页看。

Lottie 的动态属性修改怎么用?

Lottie 支持在运行时修改动画中的颜色、文字、图片等属性,这个功能叫 Dynamic Properties。Android 上通过 addValueCallback 指定某个图层的某个属性在每一帧的值,iOS 上用 LOTValueDelegate。常见场景是换肤——同一套动画,深色模式下调色板一换就行,不用导出两份 JSON。但要注意,动态修改只对 Lottie 支持的属性类型有效,自定义效果和表达式是改不了的。

Lottie 性能优化有哪些手段?

几个实用的:开启硬件加速(Android 上 setLayerType)、用 LottieComposition 缓存避免重复解析、控制帧率(没必要 60fps 的动画降到 30fps 能省一半开销)、预加载关键动画。另外 Lottie 现在也支持 dotLottie 格式,是 JSON 的 zip 压缩版本,体积更小加载更快。如果动画包含图片资源,dotLottie 还能把图片一起打包,避免资源管理混乱。

标签:Lottie