news 2026/9/24 14:46:35

Semi Design Lottie 组件实战:在 React 项目中渲染与精细控制 Lottie 动画

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Semi Design Lottie 组件实战:在 React 项目中渲染与精细控制 Lottie 动画
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】semi-design

🚀A modern, comprehensive, flexible design system and React UI library, AI-friendly built-in.🎨Provide 3000+ Design Tokens, easy to build your design system. Make Semi Design to Any Design.🧑🏻‍💻 Design to Code in one click

项目地址:https://gitcode.com/gh_mirrors/se/semi-design
点击查看免费下载

Semi Design 在 v2.62.0 起提供内置Lottie组件,它基于lottie-web封装,让开发者无需关心动画容器的创建与销毁、动画本身的生命周期管理,即可在 React 项目中便捷渲染 Lottie 动画。本文围绕官方文档(content/plus/lottie/index-en-US.md)讲解完整使用方式:从 CDN 加载与资源打包两种引入模式、params全部常用配置项,到获取动画实例与全局 Lottie 进行精细控制,并结合 semi-ui/lottie 与 semi-foundation/lottie 的源码剖析其内部实现原理,帮你写出可复制、可维护的 Lottie 动画代码。

使用场景与设计动机

Lottie 动画文件由设计师通过 After Effects 等工具导出为 JSON,体积小、矢量缩放不模糊,广泛用于加载提示、空状态、交互动效等场景。Semi Design 的 Lottie 组件封装了lottie-web,使动画渲染更简单可控,相比直接使用lottie-web具有三点核心优势:

  • 无需关心动画容器的创建与销毁:组件内部自动生成渲染容器,组件卸载时自动销毁动画实例;
  • 无需关心动画本身的生命周期:挂载初始化、params变更重建、卸载销毁均由组件与 Foundation 层接管;
  • 更易与 React 项目结合使用:以声明式 props 接入,支持受控的尺寸、样式与回调。

快速上手:引入与版本要求

Lottie 组件从v2.62.0开始支持,从@douyinfe/semi-ui顶层直接导入即可:

import { Lottie } from '@douyinfe/semi-ui';

在 packages/semi-ui/index.ts 中可以看到Lottie与其他组件一起被统一导出(export { default as Lottie } from "./lottie"),其组件实现位于 packages/semi-ui/lottie/index.tsx,底层依赖lottie-web(packages/semi-foundation/package.json 中声明为lottie-web: ^5.13.0),由 semi-foundation 的LottieFoundation负责核心逻辑。

基本用法:两种动画资源加载方式

根据动画 JSON 资源的存放位置,Lottie支持两种加载模式,二者通过params中的pathanimationData区分(二者互斥)。

模式一:动画 JSON 位于 CDN

当动画资源通过 URL 提供时,将path属性传入params

import { Lottie } from '@douyinfe/semi-ui'; import React from 'react'; () => { const jsonURL = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/lottie_demo.json'; return ( <div> <Lottie params={{ path: jsonURL }} width={'300px'} height={'300px'} /> </div> ); };

该模式下lottie-web会通过网络请求加载 JSON,适合动画资源独立部署、可被多个站点复用的场景(如统一动效 CDN)。

模式二:动画 JSON 打包进网站代码

当动画资源需要随前端工程一起打包时,将 JSON 对象传入animationData

import { Lottie } from '@douyinfe/semi-ui'; import React from 'react'; () => { const jsonURL = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/lottie_demo.json'; const [data, setData] = useState(''); useEffect(() => { fetch(jsonURL) .then(resp => resp.json()) .then(setData); }, []); return ( <div> <Lottie params={{ animationData: data }} width={'300px'} height={'300px'} /> </div> ); };

注意:上面 Demo 中通过fetch请求 JSON 仅用于演示。实际项目中应使用import animationData from './lottie.json'手动导入,这样动画 JSON 才会被 Webpack/Rspack/Vite 等构建工具识别并打包进网站代码,避免运行时依赖网络请求。

params 参数详解

params会被组件原样透传给lottie-weblottie.loadAnimation(官方文档中的参数说明与lottie-webloadAnimation入参保持一致)。常用参数如下:

// params { container: element, // 渲染容器,不传则由 Semi Lottie 组件自动配置并生成 renderer: 'svg', // 渲染方式,默认 SVG loop: true, // 是否开启循环,默认 true autoplay: true, // 是否自动播放,默认 true,设置为 false 时需要手动调用动画实例的 play 方法 path: 'data.json', // 动画 JSON 文件的 URL 路径(与 animationData 互斥) animationData: {/*...*/}, // 动画的 JSON 对象(与 path 互斥) /*...*/ }

各字段含义与取值建议:

参数类型默认值说明
containerElement组件自动生成渲染容器。传入后组件不再自行渲染包裹 div(见下文源码解析)
rendererstring'svg'渲染方式,svg/canvas/html,Semi 默认使用 SVG
loopboolean/numbertrue是否循环播放,也可传入数字指定循环次数
autoplaybooleantrue是否自动播放,设为false时需通过动画实例的play()手动播放
pathstring-动画 JSON 的 URL,与animationData互斥
animationDataobject-动画 JSON 对象,与path互斥

源码视角:默认值如何合并

从 packages/semi-ui/lottie/index.tsx 的getLoadParams实现可以看到,组件并非直接透传params,而是先设置containerrenderer: "svg"loop: trueautoplay: true四个默认值,再通过对象展开...this.props.params覆盖它们:

getLoadParams: () => { return { container: getContainer(), renderer: "svg", loop: true, autoplay: true, ...this.props.params, }; }

这意味着即使你不传任何参数,组件也能以"SVG 渲染 + 循环 + 自动播放"的方式直接运行;而传入params中的值会精确覆盖默认配置。

源码视角:容器如何自动管理

在 packages/semi-ui/lottie/index.tsx 的render中有一个关键分支:

if (this.props.params.container) { return null; } else { return <div ref={this.container} style={this.wrapperStyle} className={this.wrapperClassName} />; }
  • 若你在params中提供了container,组件不会渲染额外的包装元素,动画直接渲染到你指定的容器里;
  • 若未提供,组件自动渲染一个<div>作为容器,并通过getContainer(index.tsx#L50-L52)优先返回props.params.container、否则返回内部this.container.current

宽度与高度通过width/heightprops 以wrapperStyle的形式作用到这个自动生成的容器上(index.tsx#L79-L85),这也是为什么文档示例中widthheight需要以'300px'这样的字符串形式传入。

获取当前动画实例:精细控制播放

getAnimationInstance回调会在动画加载完成后收到当前AnimationItem实例。实例上提供了丰富的控制方法,例如播放、暂停、获取当前帧序号、调整播放速度等:

import { Lottie } from '@douyinfe/semi-ui'; import React from 'react'; () => { const jsonURL = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/lottie_demo.json'; return ( <div> <Lottie getAnimationInstance={animation => { console.log(animation); }} params={{ path: jsonURL }} width={'300px'} height={'300px'} /> </div> ); };

拿到实例后即可调用animation.play()animation.pause()animation.goToAndStop(frame, true)animation.setSpeed(speed)animation.currentFramelottie-webAnimationItem方法。结合autoplay: false,你可以在加载完成后按需手动触发播放。

源码视角:实例回调的触发时机

getAnimationInstance在三个时机被触发(packages/semi-foundation/lottie/foundation.ts):

  • init():组件挂载后,调用lottie.loadAnimation创建实例并立即回调;
  • handleParamsUpdate()params内容变化时,先destroy()旧实例,再重建新实例并回调;
  • 另外 index.tsx#L68-L71 的componentDidMount中也会通过this.foundation.animation回调一次,且组件通过isEqual(lodash)深度比较prevProps.paramsthis.props.params(index.tsx#L73-L77)来判定是否触发重建,因此即使params对象是每次渲染新建的,只要内容相同也不会反复销毁重建动画。

获取全局 Lottie 对象

lottie-web除了loadAnimation外还暴露全局方法(如registerAnimationdestroy等)。Semi Lottie 提供两种方式获取全局 lottie:

方式一:通过getLottieprops 回调

import { Lottie } from '@douyinfe/semi-ui'; import React from 'react'; () => { const jsonURL = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/lottie_demo.json'; console.log('lottie', Lottie.getLottie()); return ( <div> <Lottie getLottie={lottie => console.log('lottie', lottie)} params={{ path: jsonURL }} width={'300px'} height={'300px'} /> </div> ); };

方式二:通过静态方法Lottie.getLottie()

在组件类上直接调用Lottie.getLottie()即可,无需先渲染组件。其实现非常轻量——直接返回lottie-web模块本身(packages/semi-foundation/lottie/foundation.ts#L33-L35),在 packages/semi-ui/lottie/index.tsx#L35 中以静态属性static getLottie = LottieFoundation.getLottie暴露给组件使用者。

组件 API 总览

属性说明类型默认值
className类名string-
params用于配置动画相关参数lottie-weblottie.loadAnimation入参-
getAnimationInstance获取当前动画AnimationItem(animation: AnimationItem) => void-
getLottie获取全局 Lottie(lottie: Lottie) => void-
style样式CSSProperties-

另有widthheight两个非文档主表但示例中高频使用的属性,用于控制自动生成容器的尺寸。className会被拼接到semi-lottie前缀类名之后(cssClasses.PREFIX定义于 packages/semi-foundation/lottie/constants.ts)。

生命周期与销毁机制:源码级工作原理

Semi Lottie 组件采用「组件 + Foundation」的分层结构:组件层(packages/semi-ui/lottie/index.tsx)负责 DOM 与 React 生命周期,Foundation 层(packages/semi-foundation/lottie/foundation.ts)负责动画实例的创建、更新与销毁:

  1. 挂载:组件componentDidMount触发 Foundation 的init(),内部执行lottie.loadAnimation(this._adapter.getLoadParams())创建动画实例,并依次触发getAnimationInstancegetLottie回调(foundation.ts#L37-L42);
  2. 更新params变化时,handleParamsUpdate先调用旧实例的destroy()释放资源,再以新参数重建实例(foundation.ts#L44-L48);
  3. 卸载:Foundation 的destroy()中调用this.animation.destroy()彻底销毁动画,避免内存泄漏与残留渲染(foundation.ts#L50-L53)。

这套封装正是文档所说"无需关心动画容器的创建与销毁、无需关心动画本身的生命周期"的底层来源:容器由组件自动生成,实例的创建、重建、销毁全部由 Foundation 统一调度,使用方只需声明式地描述"要渲染哪个动画、以什么参数渲染"。

实战建议与注意事项

  • 优先使用animationData+ 静态 import:将 JSON 打包进产物,可减少运行时网络请求,且便于构建工具做体积分析与缓存;CDNpath模式适合多站点复用同一动效资源的场景。
  • 动态切换动画:直接更新params(如切换pathanimationData)即可,组件会基于深度比较自动销毁旧实例并加载新动画,无需手动管理。
  • 需要手动控制播放时:设置params.autoplay: false,并通过getAnimationInstance拿到的实例调用play()pause()goToAndStop()setSpeed()等方法。
  • 自定义渲染容器:若动画需要嵌入特定 DOM 结构,可在params.container中传入既有元素,此时组件不会额外渲染包装节点。
  • 在 v2.62.0 之前的版本中不存在该组件,使用前请确认@douyinfe/semi-ui的版本满足要求;动画参数明细(如渲染器能力差异、实例完整方法列表)以lottie-web官方说明为准。
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】semi-design

🚀A modern, comprehensive, flexible design system and React UI library, AI-friendly built-in.🎨Provide 3000+ Design Tokens, easy to build your design system. Make Semi Design to Any Design.🧑🏻‍💻 Design to Code in one click

项目地址:https://gitcode.com/gh_mirrors/se/semi-design
点击查看免费下载
上一篇:CANN/ge开发者工具链指南
下一篇:Nodeclub数据库连接复用:减少MongoDB连接开销

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 14:46:01

抛载检测 → 重复控制 RPT 清窗逻辑 → RPT 缓投使能 → 二阶滤波处理

可以专门 提供 储能一体机ARM通信管理单元,从ARM单元代码,主DSP代码、方案、硬件软件全部开源;一体化解决方案 提供西门子200全套解决方案,软硬件解决方案,全部源代码。 抛载检测 → 重复控制 RPT 清窗逻辑 → RPT 缓投使能 → 二阶滤波处理 前置背景: 你的逆变器是50H…

作者头像 李华