跳到主要内容

intro

核心知识点

1. Lottie 简介

说明: Lottie 是一个由 Airbnb 开发的开源库,用于解析 Adobe After Effects (AE) 通过 Bodymovin 插件导出的 JSON 格式动画,并在 Web、iOS、Android 和 React Native 等平台上进行原生渲染。它允许设计师创建复杂的动画,然后开发者可以轻松地将其集成到应用中,而无需手动重新创建或使用性能较低的 GIF/视频。

核心优势:

  • 跨平台: 一份 JSON 文件,多端渲染。
  • 高性能: 通常比 GIF 或 MP4 性能更好,尤其是在移动端。
  • 轻量级: JSON 文件通常比视频或 GIF 文件小得多。
  • 可伸缩: 基于矢量(如果未使用位图资源),动画可以无损缩放。
  • 可交互: 可以通过 API 控制动画播放、速度、进度等。

2. 核心概念

a. JSON 动画文件

说明: 这是 Lottie 的核心。AE 动画通过 Bodymovin 插件导出为 .json 文件。这个文件描述了动画的所有信息,包括图层、形状、路径、颜色、透明度、变换(位置、旋转、缩放)、关键帧、缓动曲线、甚至一些 AE 表达式。Lottie 库负责解析这个 JSON 文件并在目标平台上绘制出来。

示例 (JSON 文件片段):

{
"v": "5.7.4", // Bodymovin 版本
"fr": 30, // 帧率 (Frame Rate)
"ip": 0, // 起始帧 (In Point)
"op": 60, // 结束帧 (Out Point)
"w": 512, // 宽度 (Width)
"h": 512, // 高度 (Height)
"nm": "My Awesome Animation", // 名称 (Name)
"ddd": 0, // 是否 3D 图层 (3D Layer)
"assets": [], // 资源列表 (如图片)
"layers": [
// 图层数组
{
"ddd": 0,
"ind": 1, // 图层索引
"ty": 4, // 图层类型 (4 通常是形状图层)
"nm": "Shape Layer 1",
"sr": 1,
"ks": {
/* ... 变换属性 (Transform Properties) ... */
},
"ao": 0,
"shapes": [
/* ... 形状项 (Shape Items) ... */
],
"ip": 0,
"op": 60,
"st": 0, // 开始时间 (Start Time)
"bm": 0 // 混合模式 (Blend Mode)
}
// ... 其他图层
]
// ... 其他元数据
}

b. 渲染器 (Renderer)

说明: 在 Web 环境中,lottie-web 库支持多种渲染方式,主要有 svgcanvashtml

  • SVG: 默认渲染器。基于矢量,清晰度高,适合大多数动画。DOM 结构相对复杂,对于极其复杂的动画可能性能稍差。
  • Canvas: 使用 Canvas 2D API 绘制。对于包含大量图层或复杂效果的动画,性能通常优于 SVG。不支持某些 SVG 特性(如 CSS 样式)。
  • HTML: 将元素渲染为 HTML DOM 结构(通常是 Div)。仅支持 AE 功能的一个非常有限的子集,性能通常最差,很少使用。

选择渲染器示例:

import lottie from "lottie-web";

const animationContainer = document.getElementById("lottie-container");

const anim = lottie.loadAnimation({
container: animationContainer, // a DOM element
renderer: "svg", // 'svg', 'canvas', or 'html'
loop: true,
autoplay: true,
path: "path/to/your/animation.json", // URL to animation JSON
// 或者使用 animationData 属性直接传入 JSON 对象
// animationData: { /* JSON content */ }
});

3. 快速上手 (lottie-web)

a. 安装

说明: 可以通过 npm/yarn 安装或使用 CDN 引入 lottie-web 库。

代码示例:

# 使用 npm
npm install lottie-web

# 使用 yarn
yarn add lottie-web

或者在 HTML 中使用 CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>

b. 基本用法

说明: 需要一个 HTML 容器元素,然后使用 lottie.loadAnimation 方法加载并播放动画。

代码示例:

<!DOCTYPE html>
<html>
<head>
<title>Lottie Basic Example</title>
<style>
#lottie-container {
width: 300px;
height: 300px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="lottie-container"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
<script>
const animationContainer = document.getElementById("lottie-container");

const anim = lottie.loadAnimation({
container: animationContainer,
renderer: "svg",
loop: true,
autoplay: true,
path: "https://assets3.lottiefiles.com/packages/lf20_UJNc2t.json", // 使用 LottieFiles 的示例 URL
});

// anim 对象就是动画实例,可以用来控制动画
console.log("Animation Instance:", anim);
</script>
</body>
</html>

4. 播放控制 API

说明: lottie.loadAnimation 返回一个动画实例,该实例提供了丰富的 API 来控制动画的播放。

a. 常用控制方法

代码示例:

// 假设 anim 是通过 lottie.loadAnimation 返回的实例
const playButton = document.getElementById("play");
const pauseButton = document.getElementById("pause");
const stopButton = document.getElementById("stop");
const speedSlider = document.getElementById("speed");

playButton.addEventListener("click", () => {
anim.play();
});

pauseButton.addEventListener("click", () => {
anim.pause();
});

stopButton.addEventListener("click", () => {
anim.stop(); // 停止并回到第 0 帧
});

speedSlider.addEventListener("input", (e) => {
const speed = parseFloat(e.target.value);
anim.setSpeed(speed); // 设置播放速度,1 是正常速度
});

// 跳转到第 30 帧并播放
// anim.goToAndPlay(30, true); // 第二个参数 isFrame = true 表示第一个参数是帧数

// 跳转到第 15 帧并停止
// anim.goToAndStop(15, true);

// 设置播放方向 (1 正向, -1 反向)
// anim.setDirection(1);

b. 监听事件

说明: 可以监听动画生命周期中的各种事件。

代码示例:

// 动画数据加载完成 (DOM Ready)
anim.addEventListener("DOMLoaded", () => {
console.log("Animation data loaded");
});

// 动画播放完成 (如果 loop=false)
anim.addEventListener("complete", () => {
console.log("Animation completed");
});

// 动画单次循环完成 (如果 loop=true)
anim.addEventListener("loopComplete", () => {
console.log("Animation loop completed");
});

// 每一帧渲染时触发
anim.addEventListener("enterFrame", (event) => {
// event.currentTime 是当前时间 (秒)
// event.totalTime 是总时间 (秒)
// event.direction 是播放方向
console.log(
"Entering frame:",
Math.round(event.currentTime * anim.frameRate)
);
});

// 配置加载失败
anim.addEventListener("config_error", () => {
console.error("Configuration error loading animation");
});

// 数据加载失败
anim.addEventListener("data_failed", () => {
console.error("Data load failed");
});

// 销毁时
anim.addEventListener("destroy", () => {
console.log("Animation destroyed");
});

5. 动画交互

a. 分段播放

说明: 可以指定播放动画的某一个片段,常用于根据用户交互触发不同的动画状态。

代码示例:

const buttonA = document.getElementById("playSegmentA");
const buttonB = document.getElementById("playSegmentB");

// 假设动画第 0-29 帧是状态 A,第 30-59 帧是状态 B
const segmentA = [0, 29];
const segmentB = [30, 59];

buttonA.addEventListener("click", () => {
// playSegments(segments, forceFlag)
// segments: [[开始帧, 结束帧], [开始帧, 结束帧]...]
// forceFlag: true = 立即播放新片段, false = 等待当前片段完成后播放
anim.playSegments(segmentA, true);
});

buttonB.addEventListener("click", () => {
anim.playSegments(segmentB, true);
});

b. 鼠标悬停交互

说明: 一个常见的交互是鼠标悬停时播放动画,移出时停止或反向播放。

代码示例:

const interactiveElement = document.getElementById("lottie-container");

interactiveElement.addEventListener("mouseenter", () => {
anim.setDirection(1); // 确保正向播放
anim.play();
});

interactiveElement.addEventListener("mouseleave", () => {
// 方式一:直接停止
// anim.stop();

// 方式二:反向播放回去
anim.setDirection(-1);
anim.play();

// 方式三:播放一个特定的“退出”片段 (如果设计了的话)
// anim.playSegments([60, 80], true); // 假设 60-80 是退出动画
});

6. 性能优化

说明: 虽然 Lottie 通常性能良好,但在复杂动画或低端设备上仍需注意优化。

  • 选择合适的渲染器: 如前所述,canvas 对复杂动画可能性能更好。
  • 简化 AE 文件:
    • 减少图层数量。
    • 避免使用 AE 中非常复杂或 Bodymovin 不支持/支持不佳的效果(如某些粒子效果、复杂的渐变网格、特定第三方插件效果)。
    • 尽量使用形状图层代替遮罩(Masks),因为遮罩计算成本较高。
    • 合并路径 (Merge Paths) 可以减少渲染负担。
  • 位图资源: 如果动画包含位图(图片),确保图片经过压缩优化。可以通过 assetsPath 选项指定资源路径,让 Lottie 自动加载。
    lottie.loadAnimation({
    container: animationContainer,
    renderer: "svg",
    loop: true,
    autoplay: true,
    path: "path/to/data.json",
    assetsPath: "path/to/images/", // Lottie 会在此路径下查找 JSON 中引用的图片
    });
  • 按需加载和销毁: 不要在页面上一开始就加载所有 Lottie 动画,特别是当它们不在视口内时。使用 Intersection Observer 等技术实现按需加载。动画不再需要时,调用 anim.destroy() 释放资源。
    // 当元素离开视口或不再需要时
    if (anim) {
    anim.destroy();
    }
  • 避免高频 enterFrame 操作:enterFrame 回调中执行复杂计算可能会影响性能。

7. 高级特性与生态

  • 动态更新属性: Lottie 提供了一些实验性或特定场景下的 API(如 updateDocumentData)来尝试动态修改动画中的某些属性(如颜色、文本内容),但这依赖于 AE 文件结构和命名约定,通常比较复杂且易出错。更推荐的方式是在 AE 中预设好不同状态,通过 playSegments 切换。
  • Lottie Interactivity Library: 一个独立的库,可以让你更容易地将 Lottie 动画与滚动、鼠标移动、点击等交互联系起来,而无需编写复杂的事件监听和 goToAndStop 逻辑。
  • 框架集成: React (lottie-react), Vue (vue-lottie), Angular (ng-lottie) 等都有社区提供的封装库,简化在特定框架下的使用。
  • LottieFiles: 一个重要的社区资源网站 (lottiefiles.com),提供大量免费和付费的 Lottie 动画,还有在线测试、编辑、优化工具。
  • Bodymovin 插件: AE 插件,用于导出 JSON。其导出设置(如是否包含隐藏图层、是否导出表达式、是否将名称作为 ID 等)会影响最终的 JSON 文件和 Lottie 渲染行为。