mcpField
D
dotlottie-web

dotlottie-web

github.com/lottiefiles设计与 UI931125 次安装今天更新
代码仓库

关于 dotlottie-web

为 Web 项目集成 dotLottie 动画提供实现指南,涵盖通用 Web 与 React 包的选择。内容包括 Canvas 播放、Worker 渲染、多动画文件及常见交互模式。

主要功能

  1. 01Web 与 React 包的选择指南
  2. 02基于 Canvas 的动画播放
  3. 03Web Worker 渲染选项
  4. 04支持多动画 .lottie 文件
  5. 05播放与交互模式

适用场景

  1. 01为 Web 界面添加动画
  2. 02将复杂动画渲染移至 Worker
  3. 03构建悬停、点击或滚动控制的播放

安装

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

$npx skills add https://github.com/lottiefiles/dotlottie-web --skill dotlottie-web

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

详细介绍

dotLottie 实现指南

你是使用 dotLottie 运行时实现 Lottie 动画的专家。在 Web 项目中使用 dotLottie 时,请遵循以下指南。

选择软件包

在以下情况下使用 @lottiefiles/dotlottie-web:
  • 需要直接控制 canvas
  • 构建与框架无关的代码
  • 性能至关重要
  • 希望获得最小的打包体积
在以下情况下使用 @lottiefiles/dotlottie-react:
  • 构建 React 应用
  • 希望使用声明式组件 API
  • 需要集成 React 生命周期

安装

# Web (vanilla JS, Vue, Svelte, etc.)
npm install @lottiefiles/dotlottie-web

# React
npm install @lottiefiles/dotlottie-react

基本实现

原生 JavaScript
import { DotLottie } from '@lottiefiles/dotlottie-web';

const dotLottie = new DotLottie({
  canvas: document.getElementById('canvas') as HTMLCanvasElement,
  src: 'https://example.com/animation.lottie',
  autoplay: true,
  loop: true,
});
React
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

function Animation() {
  return (
    <DotLottieReact
      src="https://example.com/animation.lottie"
      autoplay
      loop
    />
  );
}
使用实例控制的 React
import { useRef } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import type { DotLottie } from '@lottiefiles/dotlottie-web';

function Animation() {
  const dotLottieRef = useRef<DotLottie | null>(null);

  return (
    <DotLottieReact
      src="https://example.com/animation.lottie"
      dotLottieRefCallback={(dotLottie) => (dotLottieRef.current = dotLottie)}
    />
  );
}

.lottie 与 .json

始终优先使用 .lottie 格式,而非 .json:

  • 文件更小(经过压缩)
  • 一个文件支持多个动画
  • 内嵌资源(图像、字体)
  • 支持用于交互的状态机
  • 使用插槽进行主题设置

Web Worker(推荐用于提升性能)

使用 DotLottieWorker 将动画渲染移至 Web Worker,让主线程专注于 UI 交互:

Worker 基本用法
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';

const dotLottie = new DotLottieWorker({
  canvas: document.getElementById('canvas') as HTMLCanvasElement,
  src: 'https://example.com/animation.lottie',
  autoplay: true,
  loop: true,
});
Worker 分组(多个动画)

默认情况下,所有 DotLottieWorker 实例共用同一个 worker。使用 workerId 将动画分组到不同的 worker:

// Hero animation in its own worker
const heroAnimation = new DotLottieWorker({
  canvas: heroCanvas,
  src: 'hero.lottie',
  workerId: 'hero-worker',
});

// UI animations share a different worker
const buttonAnimation = new DotLottieWorker({
  canvas: buttonCanvas,
  src: 'button.lottie',
  workerId: 'ui-worker',
});
何时使用 Worker
  • 使用 DotLottieWorker:

    • 同时运行多个动画
    • 包含许多图层的复杂动画
    • 动画与占用大量资源的 JS 操作同时运行
    • 主线程性能至关重要的移动设备
  • 使用普通的 DotLottie:

    • 单个简单动画
    • 需要同步访问帧
    • SSR 环境(不提供 worker)
使用 Worker 的 React
import { DotLottieWorkerReact } from '@lottiefiles/dotlottie-react';

function Animation() {
  return (
    <DotLottieWorkerReact
      src="animation.lottie"
      autoplay
      loop
      workerId="my-worker" // Optional: dedicate to specific worker
    />
  );
}

状态机(交互)

状态机无需编写代码即可实现交互式动画。详情请参阅状态机指南。

const dotLottie = new DotLottie({
  canvas,
  src: 'interactive.lottie', // Contains state machine
  autoplay: true,
});

// Fire events to trigger state transitions
dotLottie.stateMachineFireEvent('click');
dotLottie.stateMachineFireEvent('hover');
dotLottie.stateMachineFireEvent('custom-event');

// Set numeric/boolean/string inputs for state conditions
// See: https://github.com/LottieFiles/dotlottie-web/wiki/dotLottie-State-Machine-Guide#working-with-inputs
dotLottie.stateMachineSetNumericInput('progress', 0.5);
dotLottie.stateMachineSetBooleanInput('isActive', true);
dotLottie.stateMachineSetStringInput('mode', 'dark');
状态机事件
  • click - 用户点击或轻触
  • hover - 鼠标移入
  • unhover - 鼠标移出
  • complete - 动画播放完毕
  • 在状态机中定义的自定义事件

使用插槽设置主题

插槽支持在运行时自定义颜色或值。主题遵循 dotLottie 2.0 规范。

const dotLottie = new DotLottie({
  canvas,
  src: 'themed.lottie',
  themeId: 'dark-mode', // Use embedded theme by ID
});

// Or apply theme data directly (JSON string per dotLottie 2.0 spec)
// See: https://dotlottie.io/spec/2.0/#themes
dotLottie.setThemeData(JSON.stringify({
  rules: [
    { id: 'primary-color', value: [1, 0.34, 0.13] }, // RGB values 0-1
  ]
}));

动态覆盖插槽

插槽通过类型化 API 支持在运行时自定义动画属性。 可用插槽类型:颜色、标量、向量、渐变、文本、图像。

关键 API:getSlotIds()、getSlotType()、setColorSlot()、setScalarSlot()、 setVectorSlot()、setGradientSlot()、setTextSlot()、resetSlot()、clearSlots()。

如需查看完整的 API 参考,其中包含每种插槽类型的代码示例、动画关键帧、 重置、批量更新、常见用例(品牌设置、深色模式、进度指示器) 以及 React 集成,请参阅动态插槽参考。

标记与片段

播放指定片段
// Play frames 0-60
dotLottie.setSegment(0, 60);
dotLottie.play();

// Play by marker name (defined in animation)
dotLottie.setMarker('intro');
dotLottie.play();
获取标记
const markers = dotLottie.markers();
// Returns: [{ name: 'intro', start: 0, end: 60 }, ...]

将指定帧渲染为图像

设置 autoplay: false,避免播放超过目标帧;然后在 load 后调用 setFrame()。setFrame() 会同步渲染,因此调用后,canvas 和 dotLottie.buffer(RGBA Uint8Array)会立即保存该帧的内容。

浏览器
const dotLottie = new DotLottie({ canvas, src: 'animation.lottie', autoplay: false });

dotLottie.addEventListener('load', () => {
  dotLottie.setFrame(42);                        // render frame 42
  const dataUrl = canvas.toDataURL('image/png'); // or canvas.toBlob(cb, 'image/png')
});
Node.js(@napi-rs/canvas)
import fs from 'node:fs';
import { createCanvas } from '@napi-rs/canvas';

const canvas = createCanvas(200, 200);
const dotLottie = new DotLottie({
  canvas: canvas as unknown as HTMLCanvasElement,
  src: 'animation.lottie',
  autoplay: false,
});

dotLottie.addEventListener('load', async () => {
  dotLottie.setFrame(42);
  fs.writeFileSync('frame-42.png', await canvas.encode('png'));
  dotLottie.destroy();
});

如需自定义编码,可直接从 dotLottie.buffer 读取原始 RGBA 像素(长度 = width × height × 4)。

事件处理

dotLottie.addEventListener('load', () => {
  console.log('Animation loaded');
});

dotLottie.addEventListener('play', () => {
  console.log('Playing');
});

dotLottie.addEventListener('complete', () => {
  console.log('Animation completed');
});

dotLottie.addEventListener('frame', ({ currentFrame }) => {
  console.log('Frame:', currentFrame);
});

// Clean up
dotLottie.removeEventListener('load', handler);

性能最佳实践

1. 对复杂动画使用 Web Worker
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';

// Offload rendering to worker thread
const dotLottie = new DotLottieWorker({
  canvas,
  src: 'complex-animation.lottie',
});
2. 延迟加载动画
// Only load when visible
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadAnimation();
      observer.disconnect();
    }
  });
});
observer.observe(container);
3. 默认启用自动冻结

当动画不可见(位于视口之外)时,DotLottie 会自动冻结动画。要禁用此行为:

const dotLottie = new DotLottie({
  canvas,
  src: 'animation.lottie',
  renderConfig: {
    freezeOnOffscreen: false, // Disable auto-freeze (not recommended)
  },
});
4. 设备像素比

默认情况下,devicePixelRatio 设置为实际值的 75%,以提升性能。若要获得完整的 Retina 画质(性能开销更高):

const dotLottie = new DotLottie({
  canvas,
  src: 'animation.lottie',
  renderConfig: {
    devicePixelRatio: window.devicePixelRatio, // Full retina (higher CPU/GPU)
  },
});
5. 清理(仅原生 JS)
// Always destroy when done (vanilla JS)
dotLottie.destroy();

注意: DotLottieReact 会在卸载时自动处理清理,无需手动清理。

6. 帧插值控制
const dotLottie = new DotLottie({
  canvas,
  src: 'animation.lottie',
  useFrameInterpolation: true,  // Smooth playback (default)
  // useFrameInterpolation: false, // Match original AE frame rate
});

多动画文件

单个 .lottie 文件可以包含多个动画:

// Load specific animation by ID
dotLottie.loadAnimation('animation-2');

// Get all animation IDs
const animations = dotLottie.manifest?.animations;
// Returns: [{ id: 'animation-1' }, { id: 'animation-2' }]

Canvas 尺寸

通过 CSS 样式设置 canvas 尺寸(推荐)。DotLottie 会自动确定最佳绘制区域:

<canvas id="canvas" style="width: 400px; height: 400px;"></canvas>
自动调整为容器尺寸

使用 autoResize 渲染配置,在容器发生变化时自动调整尺寸:

const dotLottie = new DotLottie({
  canvas,
  src: 'animation.lottie',
  renderConfig: {
    autoResize: true, // Canvas resizes to fit container
  },
});

常见模式

悬停时播放
canvas.addEventListener('mouseenter', () => dotLottie.play());
canvas.addEventListener('mouseleave', () => dotLottie.pause());
点击时播放(一次)
canvas.addEventListener('click', () => {
  dotLottie.setFrame(0);
  dotLottie.setLoop(false);
  dotLottie.play();
});
随滚动位置播放
window.addEventListener('scroll', () => {
  const progress = window.scrollY / (document.body.scrollHeight - window.innerHeight);
  const frame = progress * dotLottie.totalFrames;
  dotLottie.setFrame(frame);
});
加载状态(React)
function Animation() {
  const [isLoaded, setIsLoaded] = useState(false);

  return (
    <>
      {!isLoaded && <Skeleton />}
      <DotLottieReact
        src="animation.lottie"
        style={{ opacity: isLoaded ? 1 : 0 }}
        dotLottieRefCallback={(dotLottie) => {
          dotLottie.addEventListener('load', () => setIsLoaded(true));
        }}
      />
    </>
  );
}
响应式动画
function ResponsiveAnimation() {
  return (
    <DotLottieReact
      src="animation.lottie"
      autoplay
      loop
      style={{ width: '100%', maxWidth: '400px' }}
      renderConfig={{ autoResize: true }}
    />
  );
}

调试

// Check if loaded
console.log('Loaded:', dotLottie.isLoaded);

// Get animation info
console.log('Duration:', dotLottie.duration);
console.log('Total Frames:', dotLottie.totalFrames);
console.log('Current Frame:', dotLottie.currentFrame);
console.log('Is Playing:', dotLottie.isPlaying);
console.log('Loop:', dotLottie.loop);
console.log('Speed:', dotLottie.speed);

// Get manifest (for .lottie files)
console.log('Manifest:', dotLottie.manifest);

错误处理

dotLottie.addEventListener('loadError', (error) => {
  console.error('Failed to load animation:', error);
  // Show fallback UI
});

SSR / Next.js 注意事项

dotLottie 需要浏览器 API。对于 SSR 框架:

import dynamic from 'next/dynamic';

const DotLottieReact = dynamic(
  () => import('@lottiefiles/dotlottie-react').then(mod => mod.DotLottieReact),
  { ssr: false }
);

function Animation() {
  return <DotLottieReact src="animation.lottie" autoplay loop />;
}

资源

评论

支持 Markdown