跳转至正文
移动端 指南

Lottie React Native

我们的完整指南将教你如何使用 lottie react native。涵盖 Expo 和 bare 工作流、动画控制、性能调优以及 2026 年的最佳实践。

Lottie React Native

你现在可能正处于两种情况之一:要么设计师正把一个 Lottie JSON 丢给你并问:“今天能把这个加进 App 吗?”;要么你已经接入了它,但发现动画在开发环境下表现良好,一旦涉及到真机、启动时间或 release build 时,性能压力就开始显现了。

这正是 Lottie React Native 的关键所在。基础 Demo 很容易做,但达到生产级标准却很难。区别通常在于你如何安装它、如何控制播放,以及你是将其视为无害的静态资源,还是将其纳入性能预算进行管理。

目录

为什么 Lottie 对 React Native App 至关重要

如果你曾尝试在 React Native 中手动还原精美的产品动画,你一定深知其中的痛苦。细微的动态细节会演变成堆积如山的计时逻辑、插值计算和平台差异。动画看起来可能“差不多”,但“差不多”通常达不到设计师交付的标准。

Lottie 改变了这一工作流。Airbnb 在 2016 年开源了 Lottie,这一发布彻底改变了移动端动画开发:设计师可以直接交付动画,而不再需要工程师逐帧重建。在某些企业级场景中,这种转变降低了移动 App 的开发成本,降幅达 高达 40%,根据 Airbnb Lottie 概览.

设计与工程不再为同一难题而战

Lottie React Native 的核心优势不仅在于“用 JSON 实现精美动画”,更在于关注点分离。设计师在 After Effects 中创作并使用 Bodymovin 导出,而开发者则通过原生驱动的播放器进行渲染,无需将动画逻辑转化为自定义的 code。

这一点至关重要,因为动画工作往往具有扩散性。一个简单的庆祝状态动画可能会影响设计评审、产品评审、Android 表现、iOS 表现、无障碍支持以及启动性能。Lottie 缩小了这些影响范围。

实战规则: 当动画是产品体验的一部分时,请使用 Lottie;如果只需要简单的透明度或位移过渡,则无需使用。

从用户体验的角度来看,动态效果可以提供反馈、确认操作,并让加载状态不再显得枯燥。如果你的团队正在认真考虑界面打磨、留存率或信任感,那么动画也是讨论的一部分。更广泛的 应用用户体验讨论 最终往往会指向同一个结论:快速的反馈优于静态屏幕。

Lottie 的最佳适用场景

Lottie React Native 最适合以下场景:

  • 品牌微交互 例如点赞、收藏、打勾及支付成功状态
  • 引导页插画 无需通过视频文件即可实现定制化感官
  • 加载中与空状态 在静态 UI 显得单调的场景下
  • 功能引导 当产品需要动效且不想嵌入 GIF 或 MP4 时

但它并非万能。对于基础的页面转场,React Native 自带的动画工具通常更简单。对于超大型或高交互性的动效系统,JSON 格式可能会成为一种权衡而非优势。这种权衡在进入生产环境后变得尤为重要,而这也是大多数教程过早停止的地方。

搭建 Lottie 开发环境

安装路径取决于首先做出的一个决定: Expo managed workflow 或 bare React Native. 不要混淆开发思维。大多数配置问题都源于开发者在 Expo 环境下尝试使用 bare workflow 指南,或者误以为 Expo 会屏蔽所有的 native 细节。

展示 Expo 和 Bare React Native 项目中 Lottie 动画配置步骤的流程图。

安装前请先选择工作流

如果你的应用基于 Expo 且追求最快的配置速度,除非确定需要自定义 native 开发,否则请坚持使用 Expo 路径。如果你使用的是 bare app,或者已经依赖了需要直接控制的 native modules,请将其作为普通的 native 依赖进行安装,并立即验证 iOS 和 Android 的 build 是否正常。

许多团队都低估了保持配置与项目类型一致对调试效率的提升。这也是为什么许多构建自定义 native 集成的团队会及早对比 Capgo 作为 Expo EAS 的替代方案 而不是等到应用变得难以维护时才考虑。

Expo managed 配置

对于 Expo-managed 应用,保持配置尽可能精简。

  1. 安装 package

    npx expo install lottie-react-native
  2. 重启 Metro

    npx expo start -c
  3. 在真机或模拟器上验证 先从本地 JSON 文件开始,渲染一个非常小的动画。不要同时调试大型资源和新安装的环境。

在 Expo 中有几点实用的注意事项:

  • 优先使用本地文件: 当你只想验证库是否正常工作时,远程动画调试会引入不必要的网络干扰。
  • 尽早测试 Release 模式行为: 开发模式可能会掩盖与时序和性能相关的问题。
  • 留意资源路径: JSON 文件路径错误是导致“什么都不渲染”的最常见原因之一。

Expo 是实现“跑通”的最快路径,但这并不意味着它是实现“规模化”的最快路径。

Bare React Native 配置

在 Bare 项目中,请立即安装并验证原生依赖。

  1. 安装软件包

    npm install lottie-react-native
  2. 安装 iOS pods

    cd ios && pod install && cd ..
  3. 重新构建 App

    npx react-native run-ios

    或

    npx react-native run-android

这是许多快速入门指南都会忽略的一点:安装完成后,在判定功能损坏之前,请务必进行一次完整的 Native rebuild。如果原生依赖没有被正确编译进 App,Hot reload 是无法解决问题的。

节省时间的 Bare workflow 检查项

在继续下一步之前,请对照此清单进行检查:

查看 为什么这很重要
安装后重新构建 Native modules 需要重新编译
运行 pod install 没有它,iOS 端将无法稳定运行
先从简单的本地 JSON 文件开始 将安装问题与资源文件问题隔离开来
尽早进行双平台测试 Android 和 iOS 失败的原因可能完全不同

如果包安装成功但第一个动画无法显示,通常不是安装问题,而是资源路径、组件尺寸或播放配置的问题。

展示你的第一个 Lottie 动画

第一个成功的动画应该是“枯燥”的:使用本地文件、固定尺寸、自动播放、可选循环。不要一上来就尝试条件播放、远程 JSON 或层级复杂的动画导出文件。

现代开发者的工作空间,笔记本电脑上显示着 code,显示器上运行着移动端动画 App。

添加本地动画文件

如果你还没有资源文件夹,请创建一个:

assets/
  animations/
    success.json

保持命名简单。避免空格、特殊标点以及过深的嵌套文件夹。你希望 require() 保持路径清晰直观。

如果你打算使用 Lottie 来制作品牌启动页或启动后的过渡动画,在将大型动画放入启动路径前请务必三思。尤其是当你还在优化 React Native splash screen 行为时,更是如此。.

使用 LottieView 进行渲染

与其直接将其丢进大型页面文件中,不如创建一个专门的组件:

import React from 'react';
import { View, StyleSheet } from 'react-native';
import LottieView from 'lottie-react-native';

export function SuccessAnimation() {
  return (
    <View style={styles.container}>
      <LottieView
        source={require('../assets/animations/success.json')}
        autoPlay
        loop={false}
        style={styles.animation}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  animation: {
    width: 220,
    height: 220,
  },
});

这样做有三个好处:

  • 验证库是否能正确渲染
  • 验证资源路径是否解析正确
  • 为你提供一个独立的区域,方便后续调整播放和尺寸

如果你跳过这些基础步骤,很快就会遇到一些坑:

  • 未设置宽度或高度: 动画虽然存在,但却是不可见的。
  • 错误 require() 路径: Metro 无法找到该文件。
  • 导出无效: 某些 JSON 文件在技术上是有效的,但包含了一些在移动端表现不符合预期的特性。

保持首次渲染在本地且具有确定性。你是在测试集成,而不是架构。

更佳的首屏测试方案

将组件放在一个带有中性背景的简单页面上:

import React from 'react';
import { SafeAreaView, StyleSheet } from 'react-native';
import { SuccessAnimation } from './src/SuccessAnimation';

export default function App() {
  return (
    <SafeAreaView style={styles.screen}>
      <SuccessAnimation />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
});

如果这在 iOS 和 Android 模拟器上都能正常工作,你就已经跨过了第一个真正的门槛。接下来的重点不是添加更多动画,而是学习何时使用声明式 props,以及何时通过 refs 进行直接控制。

精通 Lottie 动画控制

大多数 Lottie React Native 的 bug 都出现在动画需要响应状态变化时。Autoplay 很简单。但“当用户点赞时播放这段动画,取消点赞时反向播放,且在组件重新渲染时不要卡顿”——这才是棘手的地方。

对比图表:解释 Lottie 中声明式与命令式动画控制方法的区别,并突出各自的具体使用场景。

播放逻辑简单时使用 props

对于非交互式播放,使用 props 就足够了。

<LottieView
  source={require('../assets/animations/loading.json')}
  autoPlay
  loop
  speed={1}
/>

这种方式适用于:

  • 加载指示器
  • 被动式的 onboarding 插图
  • 装饰性的空状态

这种方式具有声明式且易读的特点。组件挂载,播放开始,并由 React 进行管理。如果动画逻辑完全可以通过 props 来描述,那就直接使用 props。

更高级的声明式场景是 progress,即将动画帧与另一个值绑定。当动画需要反映某种外部进度源时,这种方式效果很好,但对于一次性的触发事件来说不太方便。

在转向 refs 之前,先看一个直观的对比:

当状态驱动动画时使用 refs

当用户进行点击、切换或完成某个操作时,使用 ref 通常是更稳妥的选择。实际数据表明 68% 使用混合框架的开发者表示,由于在 useEffect hooks这就是为什么建立 animation.current.play() 可靠模式至关重要,正如这篇 Capacitor 相关的触发失败讨论所指出的。.

这个问题不仅限于混合应用。纯 React Native 中也会出现,尤其是开发者重新创建 ref、在挂载前触发播放,或将动画调用绑定到不稳定的 effect 时。

import React, { useRef, useState } from 'react';
import { Pressable } from 'react-native';
import LottieView from 'lottie-react-native';

export function LikeButton() {
  const animationRef = useRef<LottieView>(null);
  const [liked, setLiked] = useState(false);

  const onPress = () => {
    if (!animationRef.current) return;

    if (liked) {
      animationRef.current.play(60, 0);
    } else {
      animationRef.current.play(0, 60);
    }

    setLiked(!liked);
  };

  return (
    <Pressable onPress={onPress}>
      <LottieView
        ref={animationRef}
        source={require('../assets/animations/like.json')}
        loop={false}
        autoPlay={false}
        style={{ width: 96, height: 96 }}
      />
    </Pressable>
  );
}

可靠的点赞/取消点赞模式

这种模式在生产环境中比每次状态变化时都在 play() 内部 useEffect 调用更稳健。

原理如下:

  • 动画触发由事件负责: 按下事件是开始播放的稳定时机。
  • ref 保持本地化且持久: useRef 避免不必要的重新渲染。
  • 组件避免了 autoplay 冲突: 你不希望挂载行为与用户触发的行为发生冲突。

值得避免的常见错误:

  1. 在 ref 存在之前触发
    如果 animationRef.current 为 null 时,播放不会执行。请做好防护。

  2. 使用 autoPlay 配合命令式控制
    为播放指定一个默认控制者。

  3. 一切都靠 useEffect
    Effect 很有用,但对于 UI 操作,它们常常会引入时序问题,而不是消除问题。

如果动画要响应点击,请先在点击处理函数里触发它。再考虑使用 useEffect ,仅当单一事实来源位于该交互之外时。

生产级应用的性能调优

Lottie React Native 看起来很轻量,直到团队开始把大 JSON 文件塞进 app bundle,还纳闷启动为什么变慢。问题往往不在动画本身,而在交付策略。

一张信息图,展示 Lottie 性能调优的三大好处:减小 bundle 体积、提升帧率、降低内存占用。

团队容易踩坑的地方

最容易犯的错误,是把所有动画直接打包进 JavaScript,并且过早全部加载。根据 这份关于错误发布 Lottie JSON 的指南,在 JS bundle 里塞入过多 Lottie JSON 这类资源,会让应用启动时间 在中端设备上增加 40% 或更多,将它们转为原生资源进行按需加载是一项至关重要的优化。

这与许多团队在实践中遇到的情况一致。问题不在于单个微小的成功动画,而在于它们的堆积:

  • 引导流程动画
  • 加载状态
  • 电商交互反馈
  • 品牌化空白页
  • 以及与之并存的本地化文件和其他占用大量 bundle 的资源

如果你的 App 已经面临启动性能问题,Lottie 文件会迅速让情况恶化。

优先优化哪些内容

从导出环节开始。粗糙的动画导出文件会带来复杂度,最终在解析、内存占用和渲染稳定性上让你付出代价。不要直接照搬设计师导出的所有文件。

请参考以下生产环境检查清单:

  • 在发布前压缩 JSON: 更小的文件加载更快,且不易导致启动阶段臃肿。
  • 将非核心动画移出 JS bundle: 让启动 code 专注于应用立即需要的内容。
  • 按需加载动画: 仅在屏幕或操作需要时进行渲染。
  • 审计旧设备的表现: 现代模拟器可能会掩盖高昂的播放开销。
  • 避免将大型 Lottie 文件用于启动页装饰: 如果它对首次交互并非至关重要,就不应与应用启动抢占资源。

对于致力于移动端性能优化的团队来说, AppLighter 的移动性能指南 是非常值得阅读的参考资料,因为它将动画决策置于应用启动、渲染及 framework 权衡的大背景下进行考量。

一个残酷的事实: 如果一段精美的动画延迟了用户的首次交互,那通常是产品 Bug,而非设计亮点。

你也不应孤立地看待 React Native。使用混合栈的团队也会遇到类似的资源加载问题,而更广泛的 针对 Capacitor 应用的 动画性能指南同样适用于 Lottie 的决策。

本地文件 vs 远程交付

本地文件更可控。它们支持离线使用,消除了网络波动,且更易于测试。但缺点是容易导致 Bundle 体积过大。

远程交付能保持二进制文件更精简,但动画会面临可用性、缓存和回退机制等问题。对于非核心动效,这种权衡是可以接受的;但对于购买确认或登录成功等核心 UX 状态,这具有风险。

一个实用的划分方案如下:

资源类型 更佳默认方案
核心交互动画 本地化、优化且不臃肿
偶尔使用的促销动画 远程加载并提供回退方案
启动路径动画 仅在绝对必要时使用本地资源
极少使用的功能演示 按需加载

如果你只想应用本节中的一条规则,请遵循这一条: 将 Lottie JSON 视为性能敏感资产,而非无害的装饰.

Lottie 常见问题排查

Lottie 报错的原因通常很常见:路径错误、尺寸缺失、ref 时机不对或 JSON 文件过大。最快的调试方法是减少变量。

动画在 Android 上无法渲染

首先,确认 JSON 文件路径正确。然后为组件设置明确的尺寸。

<LottieView
  source={require('../assets/animations/success.json')}
  autoPlay
  style={{ width: 200, height: 200 }}
/>

如果问题依旧,请换一个确认可用的动画文件。这能帮你判断是文件本身的问题还是配置问题。

在旧设备上播放卡顿

这通常指向资源文件本身,而非 API 组件。

尝试以下修复方案:

  • 降低动画复杂度: 如果源文件过大,请要求导出更轻量级的版本。
  • 延迟加载: 避免与首屏渲染争夺资源。
  • 测试压缩版本: 如果压缩后的文件表现更好,说明你找到了性能瓶颈。
  • 避免同时渲染多个 Lottie 视图: 一个屏幕上出现多个动画可能会显得过于杂乱。

Ref 为 null 或 play 无效

Ref 为 null 通常意味着触发时机在 mount 之前,或者组件被条件渲染移除了。

if (animationRef.current) {
  animationRef.current.play();
}

使用以下方式保持 ref 稳定: useRef,并且不要不必要地重新创建动画组件。如果你在本地 build 时遇到反复出现的奇怪问题,清理陈旧缓存会有所帮助。简单的 Yarn cache 清理流程 有时就足以解决开发过程中由于资源缓存导致的误导性行为。

动画在不同屏幕尺寸下显示异常

不要让动画决定布局。将其放入容器中并进行明确的尺寸设置。

  • 为图标和表情使用固定边界
  • 为大型插图使用感知宽高比的包装器
  • 避免在未检查导出设计比例的情况下直接拉伸至全宽

大多数“Lottie 坏了”的反馈,最后都是布局、资源或时序问题。这个库通常只是按你的要求执行。

如果你想要最后的调试捷径:移除所有高级 prop,在居中视图里渲染一个本地动画,再一步步加回来。这比盯着繁忙的生产界面更能快速定位问题。


Capgo 能帮助团队无需等待应用商店审核,就把 JavaScript、资源和配置修复推送到 Capacitor 应用。如果你正在维护混合应用,并且需要更安全地推送更新、处理分阶段发布,以及快速从前端问题中恢复, Capgo 值得一看。

为 Capacitor 应用提供 Live Updates

当 Web 层出现线上 Bug 时,通过 Capgo 发布修复,而不用等 App Store 审核好几天。用户会在后台收到更新,原生变更则仍走正常审核流程。

博客最新动态

Capgo 为你提供打造真正专业的移动应用所需的最有价值的洞察。