-
引入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
相关推荐
Peter-Code10 分钟前
Nginx 常用操作整理(前端)Java后端的Ai之路10 小时前
06-React-PropsFlynt10 小时前
开源"间谍卫星"说数据全是真的,我把它的免key数据源挨个试了一遍Csvn11 小时前
渲染管线程序员大阳11 小时前
副队长CSS教程(33)–圆角与透明志尊宝11 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览鬼手点金12 小时前
opencode-rules 插件柳杉12 小时前
借助 Codex 和可视化工作流,从调研到完整实现,3D 大屏竟然可以这么简单IMPYLH12 小时前
HTML 的 <wbr> 元素Dovis(誓平步青云)13 小时前
常用命令藏得太深?怎么做一个快捷命令坞