vue项目 使用lottie解析动画json文件(兼容移动端)

1,285 阅读2分钟

本文例子如下:(真实渲染效果很流畅,GIF问题)

20210824-154722.gif

使用json动画文件的原因:
起初,动画是使用雪碧图做背景,通过控制background-position来实现的,但是发现动画在iPad端适配放大缩小后有问题,出现鬼畜。
为什么不使用GIF呢?
因为GIF播放的时候质量可能不高不够流畅。
解决方案是:在iPad端,动画相关的px不转rem,于是正常了,但是比例不正确,会出现模糊的情况。

于是,只能通过UI使用AE导出动画json文件,前端使用lottie来解析。

lottie使用方法:

一、安装vue-lottie包

npm install --save vue-lottie

二、在main.js引入并全局注册组件

import lottie from 'vue-lottie';
Vue.component('lottie', lottie)

三、引入资源、使用组件

/* 引入资源 */
import Lottie from '@/components/lottie' //这里我是将lottie组件从node_modules依赖里抽离出来,方便我们修改源码(样式、配置等), 组件源码在下方
import { animationData } from '@/assets/lottie/airplaneData.js'; //小飞机json资源文件,为什么是js文件,下面详解

/* 使用组件 */
<lottie :options="defaultOptions" height="0.625rem" width="0.625rem" @animCreated="handleAnimation" />
//data里面添加相应属性
data(){
    return {
        defaultOptions: { animationData: animationData },
        animationSpeed: 1,
        anim: {}
    }
}
//定义方法
methods: {
    handleAnimation: function(anim) {
        this.anim = anim;
        console.log(anim); //这里可以看到 lottie 对象的全部属性
    },
}

正常情况引入的资源文件是json,这样子就可以正常渲染了。
下面说说为什么我这里是引入js文件:

坑:(本文重点)

由于UI设计的动画有的图层较复杂,所以提供的json文件里面是有引入其它图片文件(UI得提供图片),由此引发下面这个问题:

lottie-web的图片要放在哪里才能被json读取到?

网上搜的话,应该会查到两种方案:
1、将json文件的u属性images修改为img,打包部署后,可以获取到图片;
2、将json文件的p属性直接赋值网络资源图片的url;
image.png

个人觉得两种方案都差不多,但是都不够方便,所以琢磨了一下,想出如下方案:

最佳解决方案:

将json文件格式改为js,用export导出变量,然后将u属性修改为用require引入图片,这样子就能正确且快速获取到图片的路径了。(如下图)
image.png

相关源码:

lottie组件:

<template>
  <div :style="style" ref="lavContainer"></div>
</template>

<script>
import lottie from 'lottie-web';

export default {
  name: 'lottie',
  props: {
    options: {
      type: Object,
      required: true
    },
    height: String,
    width: String
  },

  data() {
    return {
      style: {
        width: this.width ? this.width : '100%',
        height: this.height ? this.height : '100%',
        overflow: 'hidden',
        margin: '0 auto',
        zIndex: '2'
      }
    };
  },

  mounted() {
    this.anim = lottie.loadAnimation({
      container: this.$refs.lavContainer,
      renderer: 'svg',
      loop: this.options.loop !== false,
      autoplay: this.options.autoplay !== false,
      animationData: this.options.animationData,
      rendererSettings: this.options.rendererSettings
    });
    this.$emit('animCreated', this.anim)
  }
};
</script>