-
引入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<HTMLDivElement>(null)
const animationRef = useRef<any>(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
相关推荐
老华带你飞7 分钟前
学生请假管理|基于springboot 学生请假管理系统(源码+数据库+文档)前端不太难23 分钟前
如何给 RN 项目设计「不会失控」的导航分层模型用户40993225021227 分钟前
Vue3中v-show如何通过CSS修改display属性控制条件显示?与v-if的应用场景该如何区分?不会聊天真君64734 分钟前
CSS3(Web前端开发笔记第二期)discode39 分钟前
【开源项目技术分享】@host-navs 站导,一个简洁高效的网站链接导航工具站PieroPC43 分钟前
Nicegui 3.4.0 可以缩小组件之间的间距 label botton input textarea写代码的皮筏艇1 小时前
数组 forEachbytemanx1 小时前
深入源码:React 19 useActionState 与 Next.js Server Actions 的完美融合