5月30日 23:22

Lottie 动画卡顿时应该从哪些地方优化?

Lottie 性能优化不要一上来就改代码,先看它到底慢在哪里:是 JSON 太大、路径太复杂、同时播放太多,还是列表滚动时反复挂载。Lottie 本质上是把 After Effects 导出的描述数据交给运行时逐帧解释,文件越复杂,解析、布局、绘制和内存压力都会上来。比较稳的做法是先减设计稿复杂度,再做加载和播放策略,最后才调平台参数。

先把 JSON 变轻

最有效的优化往往发生在导出前。减少形状图层、合并静态元素、避免大量遮罩和表达式,比在客户端包一层缓存更可靠。帧率也要按场景取舍:启动页或按钮反馈用 24/30fps 通常够用,只有大面积流体动画才值得保留 60fps。图片资源不要直接塞进 base64,体积会膨胀,也不利于 CDN 和本地缓存。

json
{ "fr": 30, "ip": 0, "op": 72, "assets": [{ "id": "image_0", "u": "images/", "p": "logo.webp" }] }

播放策略比参数更重要

页面里能不自动播放就不要自动播放,尤其是列表、Tab 首页和弹窗背景动画。可见时播放、离屏暂停、只循环关键动画,通常比盲目开启硬件加速更稳。React 或 React Native 里还要避免父组件重渲染导致 LottieView 反复创建,动画数据最好静态 require 或 memo 化。

tsx
const source = require('./success.json'); export function SuccessLottie({ visible }: { visible: boolean }) { const ref = useRef<LottieView>(null); useEffect(() => { visible ? ref.current?.play() : ref.current?.pause(); }, [visible]); return <LottieView ref={ref} source={source} loop={false} autoPlay={false} />; }

如何定位真正的瓶颈

先用网络面板看 JSON 下载和解析耗时,再用性能工具观察掉帧发生在进入页面、开始播放还是滚动过程中。如果首次进入慢,多半是体积、远程加载和解析问题;如果播放中掉帧,多半是路径、遮罩、渐变或同时播放数量问题;如果滚动时卡,重点看挂载数量和可见区域播放策略。

团队里最好给 Lottie 建一个简单准入标准:文件大小、图层数量、最长时长、是否使用图片、是否有低端机实测。标准不需要复杂,但要能在设计交付前发现问题。否则每次都等开发接入后才说卡,返工成本会很高。

交付前要和设计约定清楚

Lottie 优化不应该只由开发兜底。设计交付时最好同时给出预览文件、目标尺寸、是否循环、是否允许降级成静态图,以及用到的字体和图片资源。开发侧则反馈真机帧率、首屏加载耗时和内存变化。这个协作看起来麻烦,但能避免动画上线前一天才发现某个遮罩在 Android 上不支持。

还有一个容易忽略的点是结束态。很多动画播放完要停在最后一帧,如果 JSON 的 op 多留了空白帧,用户会看到短暂停顿;如果循环动画首尾没有对齐,又会出现明显跳帧。这类问题不靠性能参数解决,只能回到时间轴调整。

追问

Lottie 文件越小就一定越流畅吗?

不一定,文件大小只影响下载和解析的一部分成本。一个 80KB 但包含大量路径变形、遮罩和渐变的动画,可能比一个 200KB 的图片序列更吃 CPU。优化时要区分网络体积和渲染复杂度,前者靠压缩和缓存,后者要回到 AE 图层和路径数量。踩坑点是只盯 gzip 后大小,结果低端 Android 还是掉帧。

Canvas、SVG 和原生渲染应该怎么选?

Web 端小图标、需要 DOM 可访问性或调试时,SVG 更直观;大面积、路径多、频繁播放的动画,Canvas 往往更省。React Native 里主要依赖原生 Lottie 渲染,重点不是选 SVG/Canvas,而是控制同时播放数量和资源释放。取舍在于清晰度、可交互性和性能,不能只看某个 renderer 的平均帧率。边界是动画如果依赖 AE 的高级效果,换渲染模式也可能不支持。

硬件加速是不是总应该打开?

不是。硬件加速能减少部分绘制压力,但也可能增加纹理内存,多个大尺寸动画同时播放时反而更容易抖。Android 上可以对全屏复杂动画尝试 renderMode=HARDWARE,但小图标或静态结束态未必需要。实践里要按设备分层测试,尤其关注低端机、弱网首次加载和页面切后台再回来。不要把硬件加速当成万能开关。

列表里每个 item 都有 Lottie 怎么办?

列表中最常见的坑是每个 item 都 autoPlay,滚动时动画创建和销毁叠在一起,JS 线程和 UI 线程都会被打满。更好的方案是只让当前可见或被选中的 item 播放,其余显示首帧或静态图。FlatList 还要配合 windowSizeremoveClippedSubviewsinitialNumToRender 控制挂载数量。取舍是交互反馈会变克制,但滚动体验会明显稳定。

什么时候应该放弃 Lottie,改用视频或静态图?

如果动画包含大量粒子、模糊、阴影、3D、长时间渐变背景,Lottie 不一定是合适载体。它适合矢量、短时、可缩放的 UI 动效,不适合把复杂视频效果硬转成 JSON。边界判断很简单:优化后仍然掉帧、JSON 难以维护、设计还要大量 AE 特效时,可以换 MP4/WebM 或首帧静态图。性能优化不是坚持某个技术,而是让用户少等、少卡、少耗电。

标签:Lottie