跳转至正文
移动端 指南

Lottie React Native

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

Lottie React Native

你现在可能正处于两种情况之一:要么设计师丢给你一个 Lottie JSON 并问:“今天能把这个放进 App 里吗?”;要么你已经接好了,发现动画在开发环境没问题,但一旦上真机、考虑启动时间和 release build,就开始觉得它很贵。

这正是 Lottie React Native 有意思的地方。基础 Demo 很容易,但要达到生产级标准却并不简单。差别通常在于你怎么安装、怎么控制播放,以及你是把动画文件当成无关紧要的资源,还是当成性能预算的一部分。

目录

为什么 Lottie 对 React Native 应用至关重要

如果你曾在 React Native 中手动还原精美的产品动画,就知道有多痛苦。细小的动效细节会变成一堆时序逻辑、插值和平台差异。动画看起来可能很接近,但“接近”通常并不是设计师交付的效果。

Lottie 改变了这一工作流。Airbnb 于 2016 年开源了 Lottie,这次开源改变了移动动画的开发方式:设计师可以直接交付动画,而不必让工程师逐帧重建。在某些企业场景中,这一转变使移动应用开发成本降低了 高达 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 托管工作流或原生 React Native。不要混淆这两种思维模型。大多数配置问题都源于开发者在 Expo 中遵循原生工作流指南,或误以为 Expo 会抽象掉所有原生细节。

展示在 Expo 和原生 React Native 项目中设置 Lottie 动画步骤的流程图。

安装前先选好工作流

如果你的应用基于 Expo 且希望最快完成设置,除非确定需要自定义原生开发,否则请坚持使用 Expo 路径。如果你使用的是原生应用,或已依赖需要直接控制的 native modules,请将其作为常规原生依赖安装,并立即验证 iOS 和 Android 构建。

许多团队低估了保持配置与项目类型一致对调试的简化作用。这也是为什么许多构建自定义原生集成的团队会对比 Capgo 作为 Expo EAS 的替代方案 尽早开始,而不是等到应用变得难以修改时再动手。

Expo managed 模式配置

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

  1. 安装软件包

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

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

在 Expo 中,有几个实用要点需要注意:

  • 优先使用本地文件: 当你只是想验证库是否工作时,远程动画调试只会增加网络噪音。
  • 尽早测试发布行为: 开发模式可能会掩盖与定时和性能相关的问题。
  • 监控资源路径: JSON 文件位置错误是导致“什么都不渲染”的最常见原因之一。

Expo 是通往“能跑起来”的最快路径。但这并不意味着它是通往“可扩展”的最快路径。

Bare React Native 环境配置

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

  1. 安装软件包

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

    cd ios && pod install && cd ..
  3. 重新构建应用

    npx react-native run-ios

    或

    npx react-native run-android

这是许多快速入门指南会跳过的一步:安装后,在断定某处出错之前,先进行一次完整的原生重新构建。Hot reload 无法挽救那些未正确编译到应用中的原生依赖项。

Bare workflow 省时检查项

在继续之前,请使用此简短检查清单:

查看 为什么这很重要
安装后重新构建 原生模块需要重新编译
运行 pod install iOS 上缺少此步骤会导致不稳定
先使用简单的本地 JSON 将安装问题与资源问题隔离
尽早测试两个平台 Android 和 iOS 可能因不同原因失败

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

展示你的第一个 Lottie 动画

第一个能跑的动画应该尽量简单。本地文件、固定尺寸、自动播放,循环可选。别一上来就用条件播放、远程 JSON 或层级复杂的动画导出。

一个现代开发者工作区,笔记本电脑上显示着 code,显示器上展示着一个移动端动画应用。

添加本地动画文件

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

assets/
  animations/
    success.json

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

如果你用 Lottie 做启动后的品牌加载页或过渡画面,在启动路径中放入大型动画前请三思。尤其是当你还在调整 React Native 启动屏行为.

使用 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 描述,就保留在那里。

一个更高级的声明式用例是 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 调用更稳健。

原理如下:

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

值得避免的常见错误:

  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% 或更多,并将它们移至原生资源以实现按需加载,是一项关键优化。

这与许多团队在实际中观察到的情况一致。问题不在于单个微小的成功动画,而在于累积效应:

  • onboarding 动效
  • 加载状态
  • 电商交互反馈
  • 品牌空状态页面
  • 与它们放在一起的 locale 文件及其他占用 bundle 体积较大的资源

如果你的应用已经存在启动性能预算问题,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 没反应

空引用通常意味着触发器在挂载前就执行了,或者组件被条件移除。

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

保持 ref 稳定,使用 useRef,并且不要不必要地重新创建动画组件。如果在本地构建中调试反复出现的异常行为,清除过期缓存可能有帮助。一个简单的 Yarn 缓存清理流程 有时足以消除开发期间误导性的资源行为。

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

不要让动画决定布局。将其放入容器内,并有意设置尺寸。

  • 为图标和表情反应使用固定边界
  • 为大型插图使用支持宽高比的包装器
  • 避免在未检查导出内容的预期构图时拉伸至全宽

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

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


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

为 Capacitor 应用提供 Live Updates

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

博客最新动态

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