- 前端
- 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
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中的path与animationData区分(二者互斥)。
模式一:动画 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-web的lottie.loadAnimation(官方文档中的参数说明与lottie-web的loadAnimation入参保持一致)。常用参数如下:
// 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 互斥) /*...*/ }各字段含义与取值建议:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
container | Element | 组件自动生成 | 渲染容器。传入后组件不再自行渲染包裹 div(见下文源码解析) |
renderer | string | 'svg' | 渲染方式,svg/canvas/html,Semi 默认使用 SVG |
loop | boolean/number | true | 是否循环播放,也可传入数字指定循环次数 |
autoplay | boolean | true | 是否自动播放,设为false时需通过动画实例的play()手动播放 |
path | string | - | 动画 JSON 的 URL,与animationData互斥 |
animationData | object | - | 动画 JSON 对象,与path互斥 |
源码视角:默认值如何合并
从 packages/semi-ui/lottie/index.tsx 的getLoadParams实现可以看到,组件并非直接透传params,而是先设置container、renderer: "svg"、loop: true、autoplay: 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),这也是为什么文档示例中width、height需要以'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.currentFrame等lottie-web的AnimationItem方法。结合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.params与this.props.params(index.tsx#L73-L77)来判定是否触发重建,因此即使params对象是每次渲染新建的,只要内容相同也不会反复销毁重建动画。
获取全局 Lottie 对象
lottie-web除了loadAnimation外还暴露全局方法(如registerAnimation、destroy等)。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-web的lottie.loadAnimation入参 | - |
getAnimationInstance | 获取当前动画AnimationItem | (animation: AnimationItem) => void | - |
getLottie | 获取全局 Lottie | (lottie: Lottie) => void | - |
style | 样式 | CSSProperties | - |
另有width、height两个非文档主表但示例中高频使用的属性,用于控制自动生成容器的尺寸。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)负责动画实例的创建、更新与销毁:
- 挂载:组件
componentDidMount触发 Foundation 的init(),内部执行lottie.loadAnimation(this._adapter.getLoadParams())创建动画实例,并依次触发getAnimationInstance与getLottie回调(foundation.ts#L37-L42); - 更新:
params变化时,handleParamsUpdate先调用旧实例的destroy()释放资源,再以新参数重建实例(foundation.ts#L44-L48); - 卸载:Foundation 的
destroy()中调用this.animation.destroy()彻底销毁动画,避免内存泄漏与残留渲染(foundation.ts#L50-L53)。
这套封装正是文档所说"无需关心动画容器的创建与销毁、无需关心动画本身的生命周期"的底层来源:容器由组件自动生成,实例的创建、重建、销毁全部由 Foundation 统一调度,使用方只需声明式地描述"要渲染哪个动画、以什么参数渲染"。
实战建议与注意事项
- 优先使用
animationData+ 静态 import:将 JSON 打包进产物,可减少运行时网络请求,且便于构建工具做体积分析与缓存;CDNpath模式适合多站点复用同一动效资源的场景。 - 动态切换动画:直接更新
params(如切换path或animationData)即可,组件会基于深度比较自动销毁旧实例并加载新动画,无需手动管理。 - 需要手动控制播放时:设置
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
相关推荐
Semi Design Lottie 组件完全指南:在 React 中渲染与掌控 Lottie 动画
Semi Design Lottie 组件完全指南:在 React 中渲染与掌控 Lottie 动画 Semi Design 在 @douyinfe/semi
前端UI组件设计系统Semi Design 中的 Lottie 动画组件详解
Semi Design 中的 Lottie 动画组件详解 什么是 Lottie 动画? Lottie 是一种基于 JSON 格式的矢量动画解决方案,由 Airb
前端UI组件设计系统wp-calypso 中的 AnimatedIcon 组件:基于 Lottie 的 After Effects 动画渲染实战指南
wp calypso 中的 AnimatedIcon 组件:基于 Lottie 的 After Effects 动画渲染实战指南 <AnimatedIcon /
前端CMS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考