-
引入lottie.json即可
-
可配置加载完成后索要循环的片段
-
帧数看json文件开头就可
-
我看到动画文件的信息:
"fr":30 - 帧率30fps
"ip":0 - 起始帧0
"op":124 - 结束帧124

'use client'
import { useEffect, useRef } from 'react'
import lottie from 'lottie-web'interface LottieAnimationProps {
path?: string
animationData?: unknown
className?: string
width?: number | string
height?: number | string
renderer?: 'svg' | 'canvas' | 'html'
startFrame?: number
endFrame?: number
speed?: number
speedLoop?: number
}export default function LottieAnimation({
path,
animationData,
className = '',
width = 500,
height = 500,
startFrame = 58,
endFrame = 124,
speed = 1,
speedLoop = 1,
renderer = 'canvas',
}: LottieAnimationProps) {
const containerRef = useRef(null)
const animationRef = useRef(null) // eslint-disable-line @typescript-eslint/no-explicit-any
const isInitializedRef = useRef(false)// 使用useRef存储参数,避免依赖变化
const paramsRef = useRef({
path,
animationData,
startFrame,
endFrame,
speed,
speedLoop,
renderer
})useEffect(() => {
if (!containerRef.current || isInitializedRef.current) {
return;
}isInitializedRef.current = true const params = paramsRef.current let animation: any = null; // eslint-disable-line @typescript-eslint/no-explicit-any // 创建动画实例 animation = lottie.loadAnimation({ container: containerRef.current!, renderer: params.renderer, loop: false, autoplay: false, ...(params.path ? { path: params.path } : { animationData: params.animationData }), }); animationRef.current = animation // 播放状态管理 let isFirstPlay = true; let isLooping = false; let currentDirection = -1; // -1: 反向(124→54), 1: 正向(54→124) // 数据准备完成 animation.addEventListener('data_ready', () => { animation.setSpeed(params.speed); // 第一次播放:0-124帧 animation.goToAndStop(0, true); animation.play(); }); // 双向循环播放函数 const startLoop = () => { if (!isLooping) return; if (currentDirection === -1) { // 反向播放:124→54 animation.playSegments([params.endFrame, params.startFrame], true); } else { // 正向播放:54→124 animation.playSegments([params.startFrame, params.endFrame], true); } }; // 监听播放完成 animation.addEventListener('complete', () => { if (isFirstPlay) { isFirstPlay = false; isLooping = true; animation.setSpeed(params.speedLoop); startLoop(); } else if (isLooping) { // 循环播放完成,切换方向 currentDirection *= -1; startLoop(); } }); return () => { isInitializedRef.current = false if (animation) { animation.removeEventListener('data_ready'); animation.removeEventListener('complete'); animation.destroy(); animationRef.current = null } };}, [])
return (
<div
ref={containerRef}
className={className}
style={{ width, height }}
/>
)
}<LottieAnimation path="/lottie_home.json" width={500} height={500} renderer="canvas" />
react-lottie动画组件封装
殇蓝2025-09-29 10:59
相关推荐
Csvn8 小时前
WASM修己xj9 小时前
我用 AI 给自己写了一个 Markdown 编辑器,然后把它开源了FRing039 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)幸运小猿10 小时前
模拟慢上传-处理超时重试image 丢失线上问题锋行天下11 小时前
Langgraph-cli 本地构建失败,改用服务器docker构建的流程moshuying11 小时前
网购能买Token了!h_654321011 小时前
echarts实现柱状图加一条横线风骏时光牛马12 小时前
生成一个后端标题,只需要一个标题,不需要其他的任何文本。子非鱼@Itfuture12 小时前
关于前后端联调中登录状态/登录信息失效?郭小李12 小时前
openFeign入门