前言

一谈到前端动画,最先想到的就是css3,当然这是其中一种方式,甚至有许多动画库,aniamte.css就是其中的一种。

我之前也谈到过三种做前端动画的方式 https://blog.csdn.net/glorydx/article/details/116102127

但现在,再补充一种,由设计师将动画设计好,形成json文件,前端直接渲染的动画。当然gif也可以,但json相对来说体积更好,更不容易失真。

言归正传,前端如何渲染json动画?

简单介绍

前端最普遍使用的渲染json的插件是lottie,我也不对它多做文字介绍,感兴趣的同学前往官网进一步了解https://airbnb.design/lottie/

根据项目的不同,lottie分为几个不同的平台,分别是
lottie-web: https://github.com/airbnb/lottie-web
lottie-android: https://github.com/airbnb/lottie-android
lottie-ios: https://github.com/airbnb/lottie-ios
lottie-react-native: https://github.com/lottie-react-native/lottie-react-native

vue通常使用lottie-web,今天以lottie-web为例,介绍这个插件。

安装

npm install lottie-web

vue组件使用

先准备好一些json的动画,用js导出,这里这样做是因为vue eslint 导入的限制。
在这里插入图片描述

vue3组件 animationIcon 代码

<template>
  <div
    class="dx-icon-animaiton-warpper"
    :class="IconClass"
    @mouseenter="handlePlay"
    @mouseleave="handleStop"
    ref="animation"
    :style="{ width, height }"
    :id="randomID"
  ></div>
</template>

<script>
import { defineComponent, ref, onMounted, nextTick } from 'vue'
// 引入json文件,我放在js里面导出
import * as iconSource from './iconSource/animation.js'
import lottie from 'lottie-web'
import { randomString } from '@/common/index'

export default defineComponent({
  name: 'Lottie',
  props: {
    width: {
      type: String,
      default: '100px'
    },
    height: {
      type: String,
      default: '100px'
    },
    src: {
      type: String,
      default: ''
    },
    jsonData: {
      type: Object,
      default: undefined
    },
    /** 是否自动播放,false则只会在hover状态下播放,true为自动播放 */
    autoplay: {
      type: Boolean,
      default: true
    },
    /** 是否循环播放,false只会播放一次 */
    loop: {
      type: Boolean,
      default: true
    },
    jsonDataName: {
      type: String,
      default: ''
    },
    color: {
      type: String,
      default: ''
    },
    // 执行动画的速度,1为1秒
    speed: {
      type: Number,
      default: 1
    }
  },
  setup(props) {
    const animation = ref(null)
    let lottieControl = {}

    const randomID = randomString(6)
    const IconClass = ref('')

    if (props.color) {
      IconClass.value = 'dx-icon-color-warpper'
    }

    onMounted(() => {
      if (animation.value) {
      	// lottie.loadAnimation的返回值是用来控制该动画的实例
        lottieControl = lottie.loadAnimation({
          // name是控制具体某一个动画的关键
          name: randomID,
          container: animation.value,
          renderer: 'svg',
          // 是否循环播放 默认为true,如果是false,每次启动播放,只会播放一次
          loop: props.loop,
          // 是否在一开始就启动播放
          autoplay: props.autoplay,
          path: props.src,
          // animationData只能加载本地json,优先级高于path
          animationData: props.jsonData || iconSource[props.jsonDataName]
        })
        // 比如来控制播放速度
        lottieControl.setSpeed(props.speed)
      }

      nextTick(() => {
        try {
          const svgDom = document.querySelector(`#${randomID} > svg`)
          if (svgDom && props.color) {
            svgDom.style.filter = `drop-shadow(${props.color} 0px -10000px)`
          }
        } catch (error) {}
      })
    })

    const handlePlay = () => {
      if (!props.autoplay) {
      	// 控制动画的播放
        lottieControl.play(randomID)
      }
      // lottieControl.goToAndStop(props.jsonDataName)
    }

    const handleStop = () => {
      if (!props.autoplay) {
      	// 停止播放
        lottieControl.stop(randomID)
      }
    }

    return {
      animation,
      IconClass,
      handlePlay,
      handleStop,
      randomID
    }
  }
})
</script>

<style lang="scss">
.dx-icon-animaiton-warpper {
  cursor: pointer;
  display: inline-block;
}

.dx-icon-color-warpper {
  overflow: hidden;
  svg {
    overflow: hidden;
    transform: translate(0px, 10000px) !important;
  }
}
</style>

相关内容

也许你会感到为难,你不是设计师,没有那么多动画json可以为你提供,
https://icons8.com/free-animated-icons该网站提供了几百种免费的json动画可以供你选择

你可以去我自己的网站查看这个组件封装使用的具体效果
http://www.dxyx-together.cn/#/home/animationIcon

在这里插入图片描述
在这里插入图片描述

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐