在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图,核心是使用 Lottie 动画库(由 Airbnb 开发,专门解析 JSON 动画文件)。以下是分步骤的完整实现方案,包含环境配置、组件集成、动画控制等核心功能:
一、核心原理
JSON 格式的动图(如 Lottie 动画)本质是通过 JSON 文件描述动画的关键帧、路径、属性变化等信息,再由 Lottie 库解析并渲染为 SVG/Canvas 动画。相比 GIF/APNG,它支持矢量无损缩放、体积更小、可交互控制(暂停 / 播放 / 反向)。
二、前置准备
-
获取 JSON 动画文件
- 设计工具导出:用 Adobe After Effects 制作动画,通过「Bodymovin」插件导出为 JSON 格式(Bodymovin 插件下载);
- 在线资源:从 LottieFiles 下载现成的 JSON 动画(免费 / 付费资源);
- 本地存放:将 JSON 文件放在项目
src/assets/animations/
目录下(如menu.json
、loading.json
)。
-
安装 Lottie 依赖
Lottie 官方提供
lottie-web
库,支持 Vue/React 等框架,执行以下命令安装:# npm 安装 npm install lottie-web --save # yarn 安装 yarn add lottie-web
三、Vue 组件集成(Vue2/Vue3 通用)
以下以「菜单按钮 JSON 动图」为例,实现完整的动画载入与控制逻辑。
1. 基础版:自动播放的 JSON 动图
适用于无需交互的场景(如装饰性动画、加载动画)。
<template>
<div class="animation-container">
<!-- 动画容器:用于承载 Lottie 渲染的动画 -->
<div ref="lottieRef" class="lottie-box"></div>
</div>
</template>
<script>
// 1. 引入 Lottie 库
import lottie from 'lottie-web';
export default {
name: 'LottieAnimation',
data() {
return {
animationInstance: null, // 存储动画实例(用于后续控制)
};
},
mounted() {
// 2. 组件挂载后初始化动画
this.initLottie();
},
beforeUnmount() {
// 3. 组件销毁前释放动画资源(避免内存泄漏)
if (this.animationInstance) {
this.animationInstance.destroy();
}
},
methods: {
initLottie() {
// 加载 JSON 动画并渲染
this.animationInstance = lottie.loadAnimation({
container: this.$refs.lottieRef, // 动画容器(通过 ref 获取 DOM)
renderer: 'svg', // 渲染方式:svg(推荐,矢量无损)/ canvas / html
loop: true, // 是否循环播放(true/false/数字,如 3 表示循环3次)
autoplay: true, // 是否自动播放
// 两种加载 JSON 的方式(二选一):
path: require('@/assets/animations/menu.json'), // 方式1:通过路径加载(推荐,支持按需加载)
// animationData: require('@/assets/animations/menu.json'), // 方式2:直接导入 JSON 数据(适合小文件)
});
// 可选:监听动画事件(如播放完成、帧变化)
this.animationInstance.addEventListener('complete', () => {
console.log('动画播放完成(仅非循环时触发)');
});
},
},
};
</script>
<style scoped>
.animation-container {
/* 父容器样式,根据布局调整 */
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.lottie-box {
/* 动画尺寸:与设计稿一致,支持百分比/固定像素 */
width: 60px;
height: 60px;
cursor: pointer; /* 如需点击交互,添加指针样式 */
}
</style>
2. 进阶版:可交互控制的 JSON 动图
适用于需要手动控制的场景(如点击切换动画状态、暂停 / 播放)。
<template>
<div class="interactive-animation">
<!-- 动画容器 -->
<div ref="lottieRef" class="lottie-box" @click="toggleAnimation"></div>
<!-- 控制按钮 -->
<div class="control-buttons">
<button @click="playAnimation">播放</button>
<button @click="pauseAnimation">暂停</button>
<button @click="reverseAnimation">反向播放</button>
</div>
</div>
</template>
<script>
import lottie from 'lottie-web';
export default {
name: 'InteractiveLottie',
data() {
return {
animationInstance: null,
isPlaying: true, // 标记当前是否在播放
};
},
mounted() {
this.initLottie();
},
beforeUnmount() {
if (this.animationInstance) {
this.animationInstance.destroy();
}
},
methods: {
initLottie() {
this.animationInstance = lottie.loadAnimation({
container: this.$refs.lottieRef,
renderer: 'svg',
loop: false, // 关闭自动循环(手动控制)
autoplay: true,
path: require('@/assets/animations/menu.json'),
});
// 监听播放状态变化
this.animationInstance.addEventListener('play', () => {
this.isPlaying = true;
});
this.animationInstance.addEventListener('pause', () => {
this.isPlaying = false;
});
},
// 1. 点击动画容器切换播放/暂停
toggleAnimation() {
if (this.isPlaying) {
this.animationInstance.pause();
} else {
this.animationInstance.play();
}
},
// 2. 播放动画
playAnimation() {
this.animationInstance.play();
},
// 3. 暂停动画
pauseAnimation() {
this.animationInstance.pause();
},
// 4. 反向播放动画
reverseAnimation() {
this.animationInstance.setDirection(-1); // 设置方向:-1 反向,1 正向
this.animationInstance.play();
},
},
};
</script>
<style scoped>
.interactive-animation {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
padding: 20px;
}
.lottie-box {
width: 80px;
height: 80px;
}
.control-buttons {
display: flex;
gap: 10px;
}
button {
padding: 6px 12px;
border: 1px solid #1890ff;
background: #fff;
color: #1890ff;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}
button:hover {
background: #1890ff;
color: #fff;
}
</style>
四、关键配置说明
Lottie 的 loadAnimation
方法支持以下核心参数,根据需求调整:
参数名 | 类型 | 说明 |
---|---|---|
container |
DOM 元素 | 必选,动画渲染的容器(通过 Vue 的 ref 获取) |
renderer |
字符串 | 可选,渲染方式:svg (推荐,矢量无损)、canvas (性能好)、html |
loop |
布尔 / 数字 | 可选,是否循环:true (无限循环)、false (仅播放一次)、3 (循环 3 次) |
autoplay |
布尔 | 可选,是否自动播放:true (默认)、false |
path |
字符串 | 可选,JSON 文件路径(如 require('@/assets/animations/xxx.json') ) |
animationData |
JSON 对象 | 可选,直接传入 JSON 数据(适合小文件,避免额外请求) |
name |
字符串 | 可选,动画名称(用于多动画管理) |
五、常见问题解决
-
JSON 动画加载失败
- 检查路径:确保
path
中的 JSON 文件路径正确(如@/assets/animations/menu.json
,@
对应src
目录); - 检查文件格式:确保 JSON 文件语法正确(可通过 JSON 校验工具 验证);
- 跨域问题:若 JSON 文件放在 CDN 上,需确保服务器开启 CORS 跨域支持。
- 检查路径:确保
-
动画尺寸异常
-
给
lottie-box
容器设置固定宽高(如width: 100px; height: 100px
),避免自适应导致拉伸; -
通过 Lottie 实例调整尺寸:
this.animationInstance.setSize(120, 120); // 动态设置宽高(单位px)
-
-
Vue3 中
this.$refs
获取不到 DOMVue3 组合式 API 中需用
ref
函数获取 DOM,示例:<script setup> import { ref, onMounted, onBeforeUnmount } from 'vue'; import lottie from 'lottie-web'; const lottieRef = ref(null); // 替代 Vue2 的 this.$refs.lottieRef let animationInstance = null; onMounted(() => { animationInstance = lottie.loadAnimation({ container: lottieRef.value, // 注意:Vue3 需用 .value 获取 DOM path: require('@/assets/animations/menu.json'), loop: true, autoplay: true, }); }); onBeforeUnmount(() => { if (animationInstance) animationInstance.destroy(); }); </script>
六、总结
- 核心流程 :安装
lottie-web
→ 准备 JSON 动画文件 → 组件中通过lottie.loadAnimation
初始化 → (可选)添加交互控制; - 优势:矢量无损缩放、体积小、可交互、跨平台(Web / 移动端通用);
- 适用场景:按钮动效、加载动画、广告 Banner、页面过渡动画等。
按照以上步骤,即可在 Vue 前端轻松载入并控制 JSON 格式的动图,替代传统的静态图片或低质量动图。