mcpField
L
lottie-animations

lottie-animations

github.com/freshtechbro设计与 UI1.2k3.0k 次安装49 周前更新
代码仓库

关于 lottie-animations

面向网页、iOS、Android 和 React Native 的 Lottie 动画集成技能,介绍如何渲染 After Effects 导出的动画,并控制播放、交互和性能。适用于需要矢量动画的界面开发者。

主要功能

  1. 01渲染 JSON 与 dotLottie 动画
  2. 02播放、暂停、跳转与循环控制
  3. 03滚动和悬停交互
  4. 04React、Vue 与 Svelte 集成
  5. 05动画压缩与性能优化

适用场景

  1. 01为按钮和图标添加动画
  2. 02制作加载与进度指示动画
  3. 03实现入门引导动画
  4. 04将动画播放与页面滚动同步

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/freshtechbro/claudedesignskills --skill lottie-animations

安装后在 Claude Code 中输入/lottie-animations确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/starter_lottie/
README.md
references/
after_effects_export.md
api_reference.md
performance_guide.md
scripts/
generate_lottie_component.py
optimize_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 图层
  • 表达式(部分支持)
  • 轨道蒙版(部分支持)

解决方案:

资源

此技能包含:

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 动画场景的替代方案

评论

支持 Markdown