惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Last Week in AI
Last Week in AI
Scott Helme
Scott Helme
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 最新话题
S
Security @ Cisco Blogs
Webroot Blog
Webroot Blog
S
Security Affairs
H
Hacker News: Front Page
TaoSecurity Blog
TaoSecurity Blog
W
WeLiveSecurity
G
GRAHAM CLULEY
T
Tenable Blog
Schneier on Security
Schneier on Security
S
Securelist
Cyberwarzone
Cyberwarzone
P
Privacy International News Feed
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recent Commits to openclaw:main
Recent Commits to openclaw:main
O
OpenAI News
N
News and Events Feed by Topic
AWS News Blog
AWS News Blog
C
Cisco Blogs
T
Threat Research - Cisco Blogs
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
美团技术团队
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
D
DataBreaches.Net
博客园_首页
MyScale Blog
MyScale Blog
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
P
Proofpoint News Feed
J
Java Code Geeks
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
Know Your Adversary
Know Your Adversary
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

博客园 - 冯叶青

OpenAI vs Anthropic API 对比:响应体、请求体、消息格式与工具调用 GitHub Actions 自动部署流程 Git分支自动合并脚本:基于时间戳的冲突解决方案 Next.js lingui.js 多语言自动提取翻译键 - ats-node React实现短信验证码输入组件 Next.js 路由参数更新最佳实践:从 replaceState 到 nextReplaceState Jenkins构建时SWR模块导入报错解决方案 解决 Jenkins 环境下 Lingui 构建报错 "btoa is not defined" git 提交 实现大图自动压缩功能 React lingui.js 多语言自动提取翻译键 - ast node html2canvas 解决截图空白问题 react 实现前端发版监测 JS根据文件名获取文件类型 JS获取本机IP地址 适用于react、vue菜单格式化工具函数 git 内容提交 实现大图拦截功能 JS实现视频截图 next.js 利用中间件(middleware.ts)实现PC与移动路由无缝切换 Android生成签名文件及对apk进行签名 JS-SDK 配置,实现微信分享功能
Next.js 中优雅地使用 Lottie 动画
冯叶青 · 2025-03-07 · via 博客园 - 冯叶青

前言:

在现代 Web 开发中,动画效果对于提升用户体验起着重要作用。Lottie 是 Airbnb 开发的一个强大的动画库,它可以解析通过 Adobe After Effects 创建并导出为 JSON 格式的动画。今天我们来看看如何在 React 项目中优雅地封装和使用 Lottie 动画。

安装依赖:

# npm
npm install lottie-react

# yarn
yarn add lottie-react

# pnpm
pnpm add lottie-react

Lottie 常用配置项

interface LottieOptions {
  loop?: boolean;              // 是否循环播放
  autoplay?: boolean;          // 是否自动播放
  initialSegment?: [number, number]; // 播放片段范围
  speed?: number;             // 播放速度
  direction?: 1 | -1;         // 播放方向:1 正向,-1 反向
  style?: React.CSSProperties; // 样式
  onComplete?: () => void;    // 播放完成回调
  onLoopComplete?: () => void; // 每次循环完成回调
  onClick?: () => void;       // 点击事件
  onMouseEnter?: () => void;  // 鼠标进入事件
  onMouseLeave?: () => void;  // 鼠标离开事件
}

实现思路:

1. 基础结构设计

src/components/LottieAnimation/
├── animations.ts // 动画配置文件
├── index.tsx // 组件主文件
├── types.d.ts // 类型声明文件
└── json/ // 存放动画 JSON 文件
  └── friendly-vehicles.json

2. 类型声明

为了支持导入 JSON 文件,我们需要添加类型声明:

declare module '*.json' {
  const value: any
  export default value
}

3. 动画配置管理

创建一个统一的动画配置文件,方便管理所有动画资源:

export const animations = {
  'friendly-vehicles': () => import('./json/friendly-vehicles.json')
  // 在这里添加更多动画
  // 'animation-name': () => import('./json/animation-name.json'),
} as const

export type AnimationName = keyof typeof animations

4. 组件实现

封装 Lottie 动画组件,支持动态加载和错误处理:

import Lottie from 'lottie-react'
import { useState, useEffect } from 'react'
import { animations, AnimationName } from './animations'

interface Props {
  size?: number
  name: AnimationName
}

const LottieAnimation: React.FC<Props> = ({ size = 120, name }) => {
  const [animationData, setAnimationData] = useState<any>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const loadAnimation = async () => {
      try {
        setLoading(true)
        const module = await animations[name]()
        setAnimationData(module.default)
      } catch (error) {
        console.error('Failed to load animation:', error)
      } finally {
        setLoading(false)
      }
    }

    loadAnimation()
  }, [name])

  if (loading || !animationData) {
    return <div style={{ width: size, height: size }}></div>
  }

  return (
    <div style={{ width: size, height: size, margin: '0 auto' }}>
      <Lottie animationData={animationData} loop={true} autoplay={true} />
    </div>
  )
}

export default LottieAnimation

组件特点:

  • 类型安全:使用 TypeScript 确保类型安全,避免运行时错误。
  • 动态加载:采用动态导入方式加载动画文件,优化首屏加载性能。
  • 统一管理:通过 animations.ts 统一管理所有动画资源,方便维护和扩展。
  • 简单易用:封装了常用的配置项,使用时只需传入必要参数。
  • 错误处理:内置错误处理机制,确保组件不会因加载失败而崩溃。

使用示例:

import LottieAnimation from '@/components/LottieAnimation'

const MyComponent = () => {
  return (
    <div>
      <h1>Lottie 动画示例</h1>
      <LottieAnimation 
        name="friendly-vehicles" 
        size={200} 
      />
    </div>
  )
}

如何添加新动画:

  • 官网:https://iconscout.com/
  • 将动画 JSON 文件放入 json 文件夹
  • 在 animations.ts 中注册新动画:
export const animations = {
  'friendly-vehicles': () => import('./json/friendly-vehicles.json'),
  'new-animation': () => import('./json/new-animation.json')
} as const