一谈到前端动画,最先想到的就是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
先准备好一些json的动画,用js导出,这里这样做是因为vue eslint 导入的限制。
<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