lottie-animations
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLottie Animations
Lottie 动画
Overview
概述
Lottie is a library for rendering After Effects animations in real-time on web, iOS, Android, and React Native. Created by Airbnb, it allows designers to ship animations as easily as shipping static assets. Animations are exported from After Effects as JSON files using the Bodymovin plugin, then rendered natively with minimal performance overhead.
When to use Lottie:
- Designer-created animations that need pixel-perfect fidelity
- Complex animated icons and micro-interactions
- Loading animations and progress indicators
- Onboarding sequences and tutorial animations
- Marketing animations and promotional content
- Alternative to GIF/video with smaller file sizes and scalability
Key advantages:
- Vector-based (scalable without quality loss)
- Significantly smaller file sizes than GIF or video
- Editable at runtime (colors, speed, segments)
- Full designer control via After Effects
- Cross-platform rendering consistency
- Interactive controls (play, pause, seek, loop)
Lottie 是一个用于在Web、iOS、Android和React Native上实时渲染After Effects动画的库。由Airbnb开发,它让设计师可以像交付静态资源一样轻松交付动画。动画通过Bodymovin插件从After Effects导出为JSON文件,然后以原生方式渲染,性能开销极低。
何时使用Lottie:
- 需要像素级保真度的设计师创建动画
- 复杂的动画图标和微交互
- 加载动画和进度指示器
- 引导流程和教程动画
- 营销动画和推广内容
- 替代GIF/视频,文件体积更小且可缩放
核心优势:
- 基于矢量(缩放不失真)
- 文件体积远小于GIF或视频
- 运行时可编辑(颜色、速度、片段)
- 设计师可通过After Effects完全控制
- 跨平台渲染一致性
- 交互式控制(播放、暂停、跳转、循环)
Core Concepts
核心概念
Lottie Format Types
Lottie 格式类型
1. JSON Lottie (.json)
- Original Lottie format
- Exported from After Effects via Bodymovin plugin
- Human-readable JSON structure
- Larger file sizes (not compressed)
- Widely supported across all platforms
2. dotLottie (.lottie)
- Modern compressed format
- ZIP archive containing JSON + assets
- Supports multiple animations and themes in one file
- Smaller file sizes (up to 90% reduction)
- Recommended for production use
1. JSON Lottie(.json)
- 原始Lottie格式
- 通过Bodymovin插件从After Effects导出
- 人类可读的JSON结构
- 文件体积较大(未压缩)
- 所有平台广泛支持
2. dotLottie(.lottie)
- 现代压缩格式
- 包含JSON和资源的ZIP归档
- 单个文件支持多个动画和主题
- 文件体积更小(最多减少90%)
- 推荐用于生产环境
Library Options
库选项
lottie-web (original library):
javascript
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 (modern, recommended):
javascript
import { DotLottie } from '@lottiefiles/dotlottie-web';
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'animation.lottie',
autoplay: true,
loop: true
});@lottiefiles/dotlottie-react (React integration):
jsx
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
<DotLottieReact
src="animation.lottie"
loop
autoplay
style={{ height: 300 }}
/>lottie-react (alternative React wrapper):
jsx
import Lottie from 'lottie-react';
import animationData from './animation.json';
<Lottie animationData={animationData} loop={true} />lottie-web(原始库):
javascript
import lottie from 'lottie-web';
lottie.loadAnimation({
container: document.getElementById('lottie-container'),
renderer: 'svg', // 或 'canvas', 'html'
loop: true,
autoplay: true,
path: 'animation.json' // 或 animationData: jsonData
});@lottiefiles/dotlottie-web(现代版,推荐):
javascript
import { DotLottie } from '@lottiefiles/dotlottie-web';
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'animation.lottie',
autoplay: true,
loop: true
});@lottiefiles/dotlottie-react(React集成):
jsx
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
<DotLottieReact
src="animation.lottie"
loop
autoplay
style={{ height: 300 }}
/>lottie-react(替代React封装):
jsx
import Lottie from 'lottie-react';
import animationData from './animation.json';
<Lottie animationData={animationData} loop={true} />Animation Data Sources
动画数据源
1. LottieFiles (lottie.host)
- 100,000+ free animations
- Direct URL embedding
- CDN hosting
2. Local JSON/dotLottie files
- Bundled with application
- Better performance (no network request)
- Version control friendly
3. After Effects export
- Custom designer animations
- Bodymovin plugin required
- Export settings critical for file size
1. LottieFiles(lottie.host)
- 10万+免费动画
- 直接URL嵌入
- CDN托管
2. 本地JSON/dotLottie文件
- 与应用捆绑
- 性能更好(无需网络请求)
- 便于版本控制
3. After Effects导出
- 自定义设计师动画
- 需要Bodymovin插件
- 导出设置对文件体积至关重要
Common Patterns
常见模式
1. Basic HTML Integration with dotLottie-web
1. 使用dotLottie-web的基础HTML集成
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>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 Component with Controls
2. 带控制功能的React组件
jsx
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>
);
};jsx
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}>播放</button>
<button onClick={handlePause}>暂停</button>
<button onClick={handleStop}>停止</button>
<button onClick={() => handleSeek(30)}>跳转到第30帧</button>
</div>
</div>
);
};3. Event Listeners and Lifecycle Hooks
3. 事件监听器和生命周期钩子
jsx
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}
/>
);
};jsx
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('动画加载完成');
const onPlay = () => console.log('动画开始播放');
const onPause = () => console.log('动画已暂停');
const onComplete = () => console.log('动画播放完成');
const onFrame = ({ currentFrame }) => console.log('当前帧:', 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. Scroll-Driven Animation with lottie-react
4. 使用lottie-react的滚动驱动动画
jsx
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}
/>
);
};jsx
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. Hover-Triggered Segment Playback
5. 悬停触发的片段播放
jsx
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>;
};jsx
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. Multi-Animation and Theme Support
6. 多动画和主题支持
jsx
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>
);
};jsx
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 for Performance (DotLottieWorker)
7. 基于Web Worker的性能优化(DotLottieWorker)
javascript
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'
});javascript
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';
// 将动画渲染卸载到Web Worker
new DotLottieWorker({
canvas: document.getElementById('canvas'),
src: 'heavy-animation.lottie',
autoplay: true,
loop: true,
workerId: 'worker-1' // 按worker分组多个动画
});
// 在独立worker中运行多个动画
new DotLottieWorker({
canvas: document.getElementById('canvas-2'),
src: 'animation-2.lottie',
autoplay: true,
loop: true,
workerId: 'worker-2'
});Integration Patterns
集成模式
With GSAP ScrollTrigger
与GSAP ScrollTrigger集成
jsx
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>
);
};jsx
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;
// 将Lottie与滚动同步
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>
);
};With Framer Motion
与Framer Motion集成
jsx
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>
);
};jsx
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 Integration
Vue 3集成
vue
<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>vue
<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 Integration
Svelte集成
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>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}>播放</button>Performance Optimization
性能优化
File Size Optimization
文件体积优化
1. Export Settings in After Effects:
- Enable "Skip images that aren't used"
- Use "Glyphs" instead of fonts when possible
- Simplify paths (reduce points in illustrator)
- Avoid effects that create large data (particles, noise)
- Use shape layers instead of vector layers
2. Compression:
- Use dotLottie format (.lottie) for automatic compression
- Run JSON through Lottie optimizer tools
- Remove unnecessary metadata
3. Lazy Loading:
jsx
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. After Effects导出设置:
- 启用“跳过未使用的图像”
- 尽可能使用“字形”替代字体
- 简化路径(在Illustrator中减少锚点)
- 避免会产生大量数据的效果(粒子、噪点)
- 使用形状图层替代矢量图层
2. 压缩:
- 使用dotLottie格式(.lottie)进行自动压缩
- 通过Lottie优化工具处理JSON
- 删除不必要的元数据
3. 懒加载:
jsx
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>
);
};Runtime Performance
运行时性能
1. Renderer Selection:
javascript
// 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 Workers:
javascript
// 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. Mobile Optimization:
javascript
// 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. 渲染器选择:
javascript
// SVG:画质最佳,复杂动画速度较慢
// Canvas:性能更好,光栅化渲染
// HTML:支持有限,仅用于简单动画
// 复杂动画优先选择Canvas
new DotLottie({
canvas: document.getElementById('canvas'),
src: 'animation.lottie',
autoplay: true,
loop: true,
renderConfig: {
devicePixelRatio: window.devicePixelRatio || 1
}
});2. Web Workers:
javascript
// 复杂动画卸载到worker
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';
new DotLottieWorker({
canvas: document.getElementById('canvas'),
src: 'heavy-animation.lottie',
autoplay: true,
loop: true
});3. 移动端优化:
javascript
// 移动端降低画质
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
}
});Common Pitfalls
常见陷阱
1. Memory Leaks from Improper Cleanup
1. 清理不当导致内存泄漏
Problem: Not destroying Lottie instances when components unmount.
Solution:
jsx
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} />;
};问题: 组件卸载时未销毁Lottie实例。
解决方案:
jsx
const SafeAnimation = () => {
const [dotLottie, setDotLottie] = React.useState(null);
React.useEffect(() => {
return () => {
// 卸载时务必销毁实例
dotLottie?.destroy();
};
}, [dotLottie]);
return <DotLottieReact src="animation.lottie" dotLottieRefCallback={setDotLottie} />;
};2. Event Listener Cleanup
2. 事件监听器未清理
Problem: Event listeners not removed, causing multiple handlers.
Solution:
jsx
useEffect(() => {
if (!dotLottie) return;
const handleComplete = () => console.log('Complete');
dotLottie.addEventListener('complete', handleComplete);
// MUST return cleanup function
return () => {
dotLottie.removeEventListener('complete', handleComplete);
};
}, [dotLottie]);问题: 未移除事件监听器,导致多个处理器同时运行。
解决方案:
jsx
useEffect(() => {
if (!dotLottie) return;
const handleComplete = () => console.log('播放完成');
dotLottie.addEventListener('complete', handleComplete);
// 必须返回清理函数
return () => {
dotLottie.removeEventListener('complete', handleComplete);
};
}, [dotLottie]);3. Large File Sizes
3. 文件体积过大
Problem: Exported JSON files are 500KB+ for simple animations.
Solutions:
- Simplify After Effects composition (reduce layers, keyframes)
- Use dotLottie format for compression
- Check Bodymovin export settings (disable "Include expressions" if not needed)
- Remove unused assets before export
- Use Lottie optimizer tools: https://lottiefiles.com/tools/lottie-editor
问题: 简单动画导出的JSON文件体积超过500KB。
解决方案:
- 简化After Effects合成(减少图层、关键帧)
- 使用dotLottie格式进行压缩
- 检查Bodymovin导出设置(不需要的话禁用“包含表达式”)
- 导出前删除未使用的资源
- 使用Lottie优化工具:https://lottiefiles.com/tools/lottie-editor
4. Animation Performance Issues
4. 动画性能问题
Problem: Animation stutters or drops frames.
Solutions:
- Switch from SVG to Canvas renderer
- Use for web worker rendering
DotLottieWorker - Reduce complexity in After Effects (fewer layers, simpler shapes)
- Lower devicePixelRatio on mobile
- Avoid animating too many properties simultaneously
问题: 动画卡顿或丢帧。
解决方案:
- 从SVG渲染器切换到Canvas渲染器
- 使用进行Web Worker渲染
DotLottieWorker - 降低After Effects中的复杂度(减少图层、简化形状)
- 移动端降低devicePixelRatio
- 避免同时动画过多属性
5. Incorrect Path/URL References
5. 路径/URL引用错误
Problem: Animation doesn't load due to CORS or incorrect paths.
Solution:
jsx
// 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" />问题: 由于CORS或路径错误,动画无法加载。
解决方案:
jsx
// 本地导入使用animationData(适用于捆绑应用)
import animationData from './animation.json';
<Lottie animationData={animationData} />
// 外部URL使用path(需要CORS头)
<DotLottieReact src="https://example.com/animation.lottie" />
// Next.js中,将文件放在public/文件夹
<DotLottieReact src="/animations/animation.lottie" />6. After Effects Export Compatibility
6. After Effects导出兼容性
Problem: Some After Effects features don't export to Lottie.
Unsupported features:
- Layer effects (drop shadows, glows) - use shape layers instead
- Blending modes (limited support)
- 3D layers
- Expressions (partial support)
- Track mattes (partial support)
Solution:
- Test export early and often
- Use LottieFiles preview before exporting
- Check Bodymovin compatibility: https://airbnb.io/lottie/#/supported-features
- Convert effects to shapes when possible
问题: 部分After Effects功能无法导出到Lottie。
不支持的功能:
- 图层效果(投影、发光)- 改用形状图层
- 混合模式(支持有限)
- 3D图层
- 表达式(部分支持)
- 轨道遮罩(部分支持)
解决方案:
- 尽早并经常测试导出
- 导出前使用LottieFiles预览
- 查看Bodymovin兼容性:https://airbnb.io/lottie/#/supported-features
- 尽可能将效果转换为形状
Resources
资源
This skill includes:
本技能包含:
scripts/
scripts/
- - Generate React/Vue/Svelte Lottie component boilerplate
generate_lottie_component.py - - Optimize Lottie JSON file size
optimize_lottie.py
- - 生成React/Vue/Svelte Lottie组件模板
generate_lottie_component.py - - 优化Lottie JSON文件体积
optimize_lottie.py
references/
references/
- - Complete API documentation for lottie-web, lottie-react, and dotlottie-web
api_reference.md - - Guide for exporting animations from After Effects
after_effects_export.md - - Detailed performance optimization strategies
performance_guide.md
- - lottie-web、lottie-react和dotlottie-web的完整API文档
api_reference.md - - 从After Effects导出动画的指南
after_effects_export.md - - 详细的性能优化策略
performance_guide.md
assets/
assets/
- - Complete React + Vite starter template with Lottie examples
starter_lottie/ - - Real-world Lottie animation patterns and use cases
examples/
- - 包含Lottie示例的完整React + Vite启动模板
starter_lottie/ - - 真实场景下的Lottie动画模式和用例
examples/
Related Skills
相关技能
- gsap-scrolltrigger - For scroll-driven Lottie animations synchronized with page scroll
- motion-framer - Combine with Framer Motion for layout animations wrapping Lottie
- animated-component-libraries - Pre-built components that may include Lottie animations
- threejs-webgl - For 3D animations beyond Lottie's 2D capabilities
- react-three-fiber - Alternative for complex 3D animated scenes
- gsap-scrolltrigger - 用于与页面滚动同步的滚动驱动Lottie动画
- motion-framer - 与Framer Motion结合,为Lottie动画添加布局动效
- animated-component-libraries - 可能包含Lottie动画的预构建组件库
- threejs-webgl - 用于Lottie 2D能力之外的3D动画
- react-three-fiber - 复杂3D动画场景的替代方案