mcpField
L
lottie

lottie

github.com/mindrally设计与 UI2881.1k 次安装3 周前更新
代码仓库

关于 lottie

面向 Web 界面开发者(包括 React)的 Lottie 动画实现技能,涵盖文件格式、性能、交互、无障碍、加载与清理。

主要功能

  1. 01dotLottie 格式指导
  2. 02延迟加载与渲染器选择
  3. 03动画和图像优化
  4. 04交互式播放模式
  5. 05减少动态效果与错误回退
  6. 06加载和清理实践

适用场景

  1. 01在 React 界面加入 Lottie 动画
  2. 02降低动画加载与渲染开销
  3. 03实现滚动联动或片段播放
  4. 04支持减少动态效果偏好

安装

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

$npx skills add https://github.com/mindrally/skills --skill lottie

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

详细介绍

Lottie 动画指南

你是 Lottie 动画、Web 性能和 JavaScript 方面的专家。实现 Lottie 动画时,请遵循以下指南。

核心原则

使用 dotLottie 格式
  • 优先使用 .lottie(dotLottie)格式,而非 .json,文件体积最多可缩小 90%
  • dotLottie 会将所有资源(图片、字体)打包到一个压缩文件中
  • 使用 lottiefiles.com 上免费的 dotLottie 转换器
安装
# For React
npm install @lottiefiles/dotlottie-react

# For vanilla JS
npm install @lottiefiles/dotlottie-web

React 实现

基本用法
import { DotLottieReact } from "@lottiefiles/dotlottie-react";

function Animation() {
  return (
    <DotLottieReact
      src="/animations/loading.lottie"
      loop
      autoplay
    />
  );
}
控制动画播放
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
import { useState } from "react";

function ControlledAnimation() {
  const [dotLottie, setDotLottie] = useState(null);

  const dotLottieRefCallback = (dotLottie) => {
    setDotLottie(dotLottie);
  };

  return (
    <>
      <DotLottieReact
        src="/animation.lottie"
        dotLottieRefCallback={dotLottieRefCallback}
      />
      <button onClick={() => dotLottie?.play()}>Play</button>
      <button onClick={() => dotLottie?.pause()}>Pause</button>
      <button onClick={() => dotLottie?.stop()}>Stop</button>
    </>
  );
}

性能优化

延迟加载
import { useEffect, useRef, useState } from "react";
import { DotLottieReact } from "@lottiefiles/dotlottie-react";

function LazyLottie({ src }) {
  const [isVisible, setIsVisible] = useState(false);
  const containerRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { rootMargin: "100px" }
    );

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    return () => observer.disconnect();
  }, []);

  return (
    <div ref={containerRef}>
      {isVisible && <DotLottieReact src={src} autoplay loop />}
    </div>
  );
}
选择合适的渲染器
// SVG renderer - best quality, good for simple animations
<DotLottieReact src="/animation.lottie" renderer="svg" />

// Canvas renderer - better performance for complex animations
<DotLottieReact src="/animation.lottie" renderer="canvas" />

// Use canvas for:
// - Complex animations with many elements
// - Lower-powered devices
// - Animations with filters/effects
减少 DOM 元素
  • 在 After Effects 中重复使用相同的图形元素
  • 简化路径并减少关键帧
  • 避免不必要的图层
  • 每个动画的 DOM 元素数量控制在 1000 个以内

动画设计最佳实践

避免性能开销大的功能
AVOID:
- Masks (use alpha matte sparingly)
- Complex blur effects
- 3D layers
- Expressions
- Uncompressed images
- Large image assets

PREFER:
- Simple shapes (fills, strokes)
- Transform animations (position, scale, rotation)
- Opacity changes
- Path animations
优化动画中的图片
- Compress images to match display size
- If max display is 400x400, don't use 1000x1000 images
- Use vector graphics when possible
- Consider converting images to shapes

交互性

光标/鼠标交互
<DotLottieReact
  src="/hover-animation.lottie"
  playMode="hover"
/>
与滚动关联的动画
import { useScroll, useTransform } from "motion/react";

function ScrollLottie() {
  const { scrollYProgress } = useScroll();
  const [dotLottie, setDotLottie] = useState(null);

  useEffect(() => {
    if (!dotLottie) return;

    const unsubscribe = scrollYProgress.on("change", (progress) => {
      dotLottie.setFrame(progress * dotLottie.totalFrames);
    });

    return unsubscribe;
  }, [dotLottie, scrollYProgress]);

  return (
    <DotLottieReact
      src="/scroll-animation.lottie"
      dotLottieRefCallback={setDotLottie}
      autoplay={false}
    />
  );
}
分段播放
function SegmentAnimation() {
  const [dotLottie, setDotLottie] = useState(null);

  const playSegment = (start, end) => {
    dotLottie?.setSegment(start, end);
    dotLottie?.play();
  };

  return (
    <>
      <DotLottieReact
        src="/multi-state.lottie"
        dotLottieRefCallback={setDotLottie}
        autoplay={false}
      />
      <button onClick={() => playSegment(0, 30)}>State 1</button>
      <button onClick={() => playSegment(30, 60)}>State 2</button>
    </>
  );
}

无障碍

尊重减少动态效果的偏好
function AccessibleAnimation() {
  const prefersReducedMotion = window.matchMedia(
    "(prefers-reduced-motion: reduce)"
  ).matches;

  if (prefersReducedMotion) {
    return <img src="/static-fallback.svg" alt="Animation description" />;
  }

  return (
    <DotLottieReact
      src="/animation.lottie"
      autoplay
      loop
      aria-label="Decorative loading animation"
    />
  );
}
提供回退方案
function AnimationWithFallback() {
  const [hasError, setHasError] = useState(false);

  if (hasError) {
    return <img src="/fallback.gif" alt="Animation" />;
  }

  return (
    <DotLottieReact
      src="/animation.lottie"
      autoplay
      onError={() => setHasError(true)}
    />
  );
}

加载策略

为大型动画使用预加载器
function AnimationWithPreloader() {
  const [isLoaded, setIsLoaded] = useState(false);

  return (
    <div className="animation-container">
      {!isLoaded && (
        <img src="/first-frame.webp" alt="" className="preloader" />
      )}
      <DotLottieReact
        src="/large-animation.lottie"
        onLoad={() => setIsLoaded(true)}
        style={{ opacity: isLoaded ? 1 : 0 }}
        autoplay
      />
    </div>
  );
}

文件大小指南

动画复杂度目标大小DOM 元素上限
简单图标< 10KB< 100
UI 动画< 50KB< 500
复杂场景< 150KB< 1500
主视觉动画< 300KB< 2500

清理

在 React 中正确清理
useEffect(() => {
  return () => {
    dotLottie?.destroy();
  };
}, [dotLottie]);

最佳实践总结

  1. 使用 dotLottie 格式以缩小文件体积
  2. 对不在视口中的动画进行延迟加载
  3. 对复杂动画使用 canvas 渲染器
  4. 避免使用蒙版、模糊和表达式
  5. 压缩并优化图片资源
  6. 尊重减少动态效果的偏好
  7. 出错时提供静态回退方案
  8. 卸载时清理动画
  9. 控制 DOM 元素数量
  10. 为大型动画使用预加载器

评论

支持 Markdown