关于 lottie-animations
面向网页、iOS、Android 和 React Native 的 Lottie 动画集成技能,介绍如何渲染 After Effects 导出的动画,并控制播放、交互和性能。适用于需要矢量动画的界面开发者。
主要功能
- 01渲染 JSON 与 dotLottie 动画
- 02播放、暂停、跳转与循环控制
- 03滚动和悬停交互
- 04React、Vue 与 Svelte 集成
- 05动画压缩与性能优化
适用场景
- 01为按钮和图标添加动画
- 02制作加载与进度指示动画
- 03实现入门引导动画
- 04将动画播放与页面滚动同步
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill lottie-animations安装后在 Claude Code 中输入/lottie-animations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/starter_lottie/README.mdreferences/after_effects_export.mdapi_reference.mdperformance_guide.mdscripts/generate_lottie_component.pyoptimize_lottie.py详细介绍
Lottie 动画
概述
Lottie 是一个用于在 Web、iOS、Android 和 React Native 上实时渲染 After Effects 动画的库。它由 Airbnb 创建,让设计师能够像交付静态资源一样轻松地交付动画。动画通过 Bodymovin 插件从 After Effects 导出为 JSON 文件,然后以极低的性能开销进行原生渲染。
适用场景:
- 需要像素级精准还原的设计师创作动画
- 复杂的动画图标和微交互
- 加载动画和进度指示器
- 新手引导流程和教程动画
- 营销动画和推广内容
- 可替代 GIF/视频,文件更小且可缩放
主要优势:
- 基于矢量(缩放时不会损失画质)
- 文件比 GIF 或视频小得多
- 支持在运行时编辑(颜色、速度、片段)
- 可通过 After Effects 完全掌控设计
- 跨平台渲染一致
- 支持交互控制(播放、暂停、跳转、循环)
核心概念
Lottie 格式类型
1. JSON Lottie(.json)
- 原始 Lottie 格式
- 通过 Bodymovin 插件从 After Effects 导出
- JSON 结构易于阅读
- 文件较大(未压缩)
- 广泛支持所有平台
2. dotLottie(.lottie)
- 现代压缩格式
- 包含 JSON 和资源的 ZIP 归档文件
- 单个文件支持多个动画和主题
- 文件更小(最多可减少 90%)
- 推荐用于生产环境
库选项
lottie-web(原始库):
import lottie from 'lottie-web';
lottie.loadAnimation({
container: document.getElementById('lottie-container'),
renderer: 'svg', // or 'canvas', 'html'
loop: true,
autoplay: true,
path: 'animation.json' // or animationData: jsonData
});
@lottiefiles/dotlottie-web(现代、推荐):
import { DotLottie } from '@lottiefiles/dotlottie-web';
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'animation.lottie',
autoplay: true,
loop: true
});
@lottiefiles/dotlottie-react(React 集成):
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
<DotLottieReact
src="animation.lottie"
loop
autoplay
style={{ height: 300 }}
/>
lottie-react(另一种 React 封装库):
import Lottie from 'lottie-react';
import animationData from './animation.json';
<Lottie animationData={animationData} loop={true} />
动画数据来源
1. LottieFiles(lottie.host)
- 100,000 多个免费动画
- 直接嵌入 URL
- 通过 CDN 托管
2. 本地 JSON/dotLottie 文件
- 与应用程序打包
- 性能更好(无需网络请求)
- 便于进行版本控制
3. After Effects 导出
- 自定义设计师动画
- 需要 Bodymovin 插件
- 导出设置对文件大小至关重要
常见模式
1. 使用 dotLottie-web 进行基础 HTML 集成
<!DOCTYPE html>
<html>
<head>
<style>
#canvas {
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="module">
import { DotLottie } from 'https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm';
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'https://lottie.host/4db68bbd-31f6-4cd8-84eb-189de081159a/IGmMCqhzpt.lottie',
autoplay: true,
loop: true
});
</script>
</body>
</html>
2. 带控件的 React 组件
import React from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
const AnimatedButton = () => {
const [dotLottie, setDotLottie] = React.useState(null);
const handlePlay = () => dotLottie?.play();
const handlePause = () => dotLottie?.pause();
const handleStop = () => dotLottie?.stop();
const handleSeek = (frame) => dotLottie?.setFrame(frame);
return (
<div>
<DotLottieReact
src="button-animation.lottie"
loop
autoplay={false}
dotLottieRefCallback={setDotLottie}
style={{ height: 200 }}
/>
<div>
<button onClick={handlePlay}>Play</button>
<button onClick={handlePause}>Pause</button>
<button onClick={handleStop}>Stop</button>
<button onClick={() => handleSeek(30)}>Seek to frame 30</button>
</div>
</div>
);
};
3. 事件监听器和生命周期钩子
import React, { useEffect } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
const EventDrivenAnimation = () => {
const [dotLottie, setDotLottie] = React.useState(null);
useEffect(() => {
if (!dotLottie) return;
const onLoad = () => console.log('Animation loaded');
const onPlay = () => console.log('Animation started');
const onPause = () => console.log('Animation paused');
const onComplete = () => console.log('Animation completed');
const onFrame = ({ currentFrame }) => console.log('Frame:', currentFrame);
dotLottie.addEventListener('load', onLoad);
dotLottie.addEventListener('play', onPlay);
dotLottie.addEventListener('pause', onPause);
dotLottie.addEventListener('complete', onComplete);
dotLottie.addEventListener('frame', onFrame);
return () => {
dotLottie.removeEventListener('load', onLoad);
dotLottie.removeEventListener('play', onPlay);
dotLottie.removeEventListener('pause', onPause);
dotLottie.removeEventListener('complete', onComplete);
dotLottie.removeEventListener('frame', onFrame);
};
}, [dotLottie]);
return (
<DotLottieReact
src="animation.lottie"
loop
autoplay
dotLottieRefCallback={setDotLottie}
/>
);
};
4. 使用 lottie-react 创建滚动驱动动画
import Lottie from 'lottie-react';
import robotAnimation from './robot.json';
const ScrollAnimation = () => {
const interactivity = {
mode: 'scroll',
actions: [
{
visibility: [0, 0.2],
type: 'stop',
frames: [0]
},
{
visibility: [0.2, 0.45],
type: 'seek',
frames: [0, 45]
},
{
visibility: [0.45, 1.0],
type: 'loop',
frames: [45, 60]
}
]
};
return (
<Lottie
animationData={robotAnimation}
style={{ height: 300 }}
interactivity={interactivity}
/>
);
};
5. 悬停触发的片段播放
import { useLottie, useLottieInteractivity } from 'lottie-react';
import likeButton from './like-button.json';
const HoverAnimation = () => {
const lottieObj = useLottie({
animationData: likeButton
});
const Animation = useLottieInteractivity({
lottieObj,
mode: 'cursor',
actions: [
{
position: { x: [0, 1], y: [0, 1] },
type: 'loop',
frames: [45, 60]
},
{
position: { x: -1, y: -1 },
type: 'stop',
frames: [45]
}
]
});
return <div style={{ height: 300, border: '2px solid black' }}>{Animation}</div>;
};
6. 多动画和主题支持
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import React, { useState, useEffect } from 'react';
const ThemedAnimation = () => {
const [dotLottie, setDotLottie] = useState(null);
const [animations, setAnimations] = useState([]);
const [themes, setThemes] = useState([]);
const [currentAnimationId, setCurrentAnimationId] = useState('');
const [currentThemeId, setCurrentThemeId] = useState('');
useEffect(() => {
if (!dotLottie) return;
const onLoad = () => {
setAnimations(dotLottie.manifest.animations || []);
setThemes(dotLottie.manifest.themes || []);
setCurrentAnimationId(dotLottie.activeAnimationId);
setCurrentThemeId(dotLottie.activeThemeId);
};
dotLottie.addEventListener('load', onLoad);
return () => dotLottie.removeEventListener('load', onLoad);
}, [dotLottie]);
return (
<div>
<DotLottieReact
src="multi-animation.lottie"
dotLottieRefCallback={setDotLottie}
animationId={currentAnimationId}
themeId={currentThemeId}
/>
{themes.length > 0 && (
<select value={currentThemeId} onChange={(e) => setCurrentThemeId(e.target.value)}>
{themes.map((theme) => (
<option key={theme.id} value={theme.id}>{theme.id}</option>
))}
</select>
)}
{animations.length > 0 && (
<select value={currentAnimationId} onChange={(e) => setCurrentAnimationId(e.target.value)}>
{animations.map((anim) => (
<option key={anim.id} value={anim.id}>{anim.id}</option>
))}
</select>
)}
</div>
);
};
7. 使用 Web Worker 提升性能(DotLottieWorker)
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';
// Offload animation rendering to a web worker
new DotLottieWorker({
canvas: document.getElementById('canvas'),
src: 'heavy-animation.lottie',
autoplay: true,
loop: true,
workerId: 'worker-1' // Group multiple animations by worker
});
// Multiple animations in separate workers
new DotLottieWorker({
canvas: document.getElementById('canvas-2'),
src: 'animation-2.lottie',
autoplay: true,
loop: true,
workerId: 'worker-2'
});
集成模式
与 GSAP ScrollTrigger 集成
import Lottie from 'lottie-react';
import gsap from 'gsap';
import ScrollTrigger from 'gsap/ScrollTrigger';
import animationData from './animation.json';
gsap.registerPlugin(ScrollTrigger);
const GSAPLottieIntegration = () => {
const lottieRef = React.useRef();
React.useEffect(() => {
const anim = lottieRef.current;
if (!anim) return;
// Sync Lottie with scroll
gsap.to(anim, {
scrollTrigger: {
trigger: '#animation-section',
start: 'top center',
end: 'bottom center',
scrub: 1,
onUpdate: (self) => {
const frame = Math.floor(self.progress * (anim.totalFrames - 1));
anim.goToAndStop(frame, true);
}
}
});
}, []);
return (
<div id="animation-section" style={{ height: '200vh' }}>
<Lottie
lottieRef={lottieRef}
animationData={animationData}
autoplay={false}
loop={false}
/>
</div>
);
};
与 Framer Motion 集成
import { motion } from 'framer-motion';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
const MotionLottie = () => {
return (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.6 }}
>
<DotLottieReact
src="animation.lottie"
loop
autoplay
style={{ height: 400 }}
/>
</motion.div>
);
};
Vue 3 集成
<script setup>
import { DotLottieVue } from '@lottiefiles/dotlottie-vue';
</script>
<template>
<DotLottieVue
style="height: 500px; width: 500px"
autoplay
loop
src="https://path-to-animation.lottie"
/>
</template>
Svelte 集成
<script lang="ts">
import { DotLottieSvelte } from '@lottiefiles/dotlottie-svelte';
import type { DotLottie } from '@lottiefiles/dotlottie-svelte';
let dotLottie: DotLottie | null = null;
function play() {
dotLottie?.play();
}
</script>
<DotLottieSvelte
src="animation.lottie"
loop={true}
autoplay={true}
dotLottieRefCallback={(ref) => dotLottie = ref}
/>
<button on:click={play}>Play</button>
性能优化
文件大小优化
1. After Effects 导出设置:
- 启用“跳过未使用的图像”
- 尽可能使用“字形”而不是字体
- 简化路径(减少 Illustrator 中的锚点)
- 避免会生成大量数据的效果(粒子、噪声)
- 使用形状图层代替矢量图层
2. 压缩:
- 使用 dotLottie 格式(.lottie)自动压缩
- 使用 Lottie 优化工具处理 JSON
- 移除不必要的元数据
3. 延迟加载:
const LazyLottie = () => {
const [shouldLoad, setShouldLoad] = React.useState(false);
React.useEffect(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
setShouldLoad(true);
}
});
observer.observe(document.getElementById('lottie-trigger'));
return () => observer.disconnect();
}, []);
return (
<div id="lottie-trigger">
{shouldLoad && <DotLottieReact src="animation.lottie" loop autoplay />}
</div>
);
};
运行时性能
1. 渲染器选择:
// SVG: Best quality, slower for complex animations
// Canvas: Better performance, rasterized
// HTML: Limited support, use only for simple animations
// For complex animations, prefer canvas
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'animation.lottie',
autoplay: true,
loop: true,
renderConfig: {
devicePixelRatio: window.devicePixelRatio || 1
}
});
2. Web Worker:
// Offload to worker for heavy animations
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';
new DotLottieWorker({
canvas: document.getElementById('canvas'),
src: 'heavy-animation.lottie',
autoplay: true,
loop: true
});
3. 移动端优化:
// Reduce quality on mobile
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
new DotLottie({
canvas: document.getElementById('canvas'),
src: isMobile ? 'animation-low.lottie' : 'animation-high.lottie',
autoplay: true,
loop: true,
renderConfig: {
devicePixelRatio: isMobile ? 1 : window.devicePixelRatio
}
});
常见问题
1. 清理不当导致内存泄漏
问题: 组件卸载时未销毁 Lottie 实例。
解决方案:
const SafeAnimation = () => {
const [dotLottie, setDotLottie] = React.useState(null);
React.useEffect(() => {
return () => {
// Always destroy instance on unmount
dotLottie?.destroy();
};
}, [dotLottie]);
return <DotLottieReact src="animation.lottie" dotLottieRefCallback={setDotLottie} />;
};
2. 清理事件监听器
问题: 未移除事件监听器,导致出现多个处理器。
解决方案:
useEffect(() => {
if (!dotLottie) return;
const handleComplete = () => console.log('Complete');
dotLottie.addEventListener('complete', handleComplete);
// MUST return cleanup function
return () => {
dotLottie.removeEventListener('complete', handleComplete);
};
}, [dotLottie]);
3. 文件体积过大
问题: 简单动画导出的 JSON 文件超过 500KB。
解决方案:
- 简化 After Effects 合成(减少图层和关键帧)
- 使用 dotLottie 格式进行压缩
- 检查 Bodymovin 导出设置(如果不需要,请禁用“Include expressions”)
- 导出前移除未使用的资源
- 使用 Lottie 优化工具:https://lottiefiles.com/tools/lottie-editor
4. 动画性能问题
问题: 动画卡顿或丢帧。
解决方案:
- 将 SVG 渲染器切换为 Canvas 渲染器
- 使用
DotLottieWorker通过 Web Worker 渲染 - 降低 After Effects 合成的复杂度(减少图层、简化形状)
- 在移动设备上调低 devicePixelRatio
- 避免同时为过多属性添加动画
5. 路径/URL 引用不正确
问题: 由于 CORS 或路径不正确,动画无法加载。
解决方案:
// Use animationData for local imports (best for bundled apps)
import animationData from './animation.json';
<Lottie animationData={animationData} />
// OR use path for external URLs (requires CORS headers)
<DotLottieReact src="https://example.com/animation.lottie" />
// For Next.js, place in public/ folder
<DotLottieReact src="/animations/animation.lottie" />
6. After Effects 导出兼容性
问题: 某些 After Effects 功能无法导出为 Lottie。
不支持的功能:
- 图层效果(投影、发光)——改用形状图层
- 混合模式(支持有限)
- 3D 图层
- 表达式(部分支持)
- 轨道蒙版(部分支持)
解决方案:
- 尽早并经常测试导出效果
- 导出前使用 LottieFiles 预览
- 查看 Bodymovin 兼容性:https://airbnb.io/lottie/#/supported-features
- 尽可能将效果转换为形状
资源
此技能包含:
scripts/
generate_lottie_component.py- 生成 React/Vue/Svelte Lottie 组件样板代码optimize_lottie.py- 优化 Lottie JSON 文件大小
references/
api_reference.md- lottie-web、lottie-react 和 dotlottie-web 的完整 API 文档after_effects_export.md- 从 After Effects 导出动画的指南performance_guide.md- 详细的性能优化策略
assets/
starter_lottie/- 完整的 React + Vite 入门模板,包含 Lottie 示例examples/- 真实场景中的 Lottie 动画模式和用例
相关技能
- gsap-scrolltrigger - 用于与页面滚动同步的滚动驱动型 Lottie 动画
- motion-framer - 与 Framer Motion 结合,为包裹 Lottie 的布局添加动画
- animated-component-libraries - 可能包含 Lottie 动画的预构建组件
- threejs-webgl - 用于实现超出 Lottie 2D 能力范围的 3D 动画
- react-three-fiber - 复杂 3D 动画场景的替代方案