在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图

发布于:2025-08-29 ⋅ 阅读:(14) ⋅ 点赞:(0)

在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图,核心是使用 Lottie 动画库(由 Airbnb 开发,专门解析 JSON 动画文件)。以下是分步骤的完整实现方案,包含环境配置、组件集成、动画控制等核心功能:

一、核心原理

JSON 格式的动图(如 Lottie 动画)本质是通过 JSON 文件描述动画的关键帧、路径、属性变化等信息,再由 Lottie 库解析并渲染为 SVG/Canvas 动画。相比 GIF/APNG,它支持矢量无损缩放、体积更小、可交互控制(暂停 / 播放 / 反向)。

二、前置准备

  1. 获取 JSON 动画文件

    • 设计工具导出:用 Adobe After Effects 制作动画,通过「Bodymovin」插件导出为 JSON 格式(Bodymovin 插件下载);
    • 在线资源:从 LottieFiles 下载现成的 JSON 动画(免费 / 付费资源);
    • 本地存放:将 JSON 文件放在项目 src/assets/animations/ 目录下(如 menu.jsonloading.json)。
  2. 安装 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 字符串 可选,动画名称(用于多动画管理)

五、常见问题解决

  1. JSON 动画加载失败

    • 检查路径:确保 path 中的 JSON 文件路径正确(如 @/assets/animations/menu.json@ 对应 src 目录);
    • 检查文件格式:确保 JSON 文件语法正确(可通过 JSON 校验工具 验证);
    • 跨域问题:若 JSON 文件放在 CDN 上,需确保服务器开启 CORS 跨域支持。
  2. 动画尺寸异常

    • 给 lottie-box 容器设置固定宽高(如 width: 100px; height: 100px),避免自适应导致拉伸;
    • 通过 Lottie 实例调整尺寸:
      this.animationInstance.setSize(120, 120); // 动态设置宽高(单位px)
      
  3. Vue3 中 this.$refs 获取不到 DOM
    Vue3 组合式 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>
    

六、总结

  1. 核心流程:安装 lottie-web → 准备 JSON 动画文件 → 组件中通过 lottie.loadAnimation 初始化 → (可选)添加交互控制;
  2. 优势:矢量无损缩放、体积小、可交互、跨平台(Web / 移动端通用);
  3. 适用场景:按钮动效、加载动画、广告 Banner、页面过渡动画等。

按照以上步骤,即可在 Vue 前端轻松载入并控制 JSON 格式的动图,替代传统的静态图片或低质量动图。


网站公告

今日签到

点亮在社区的每一天
去签到