背景
👏最近在工作过程中遇到一些用css3不好实现的动画,gif又满足不了需求,那么就试试lottie动画吧(需要你们的ui小伙伴提供动画的json文件哦~)
🥇文末分享源代码。记得点赞+关注+收藏!
1.实现效果
2.实现原理
2.1 lottie
lottie:
Lottie适用于Android、iOS、Web、React Native和Windows,通过Bodymovin解析Adobe After Effects动画导出的json,并在移动端和Web上原生渲染它们!
前端直接引用lottie-web库即可,默认的渲染方式是svg,前端无需关心动画的过程。
官方文档:http://airbnb.io/lottie/#/
源码地址:https://github.com/airbnb/lottie
lottie-web地址:https://github.com/airbnb/lottie-web
npm地址:npm地址:https://www.npmjs.com/package/lottie-web
2.2 使用
静态CDN引入:https://cdnjs.com/libraries/lottie-web
本地引入:https://github.com/airbnb/lottie-web/tree/master/build/player
NPM安装:
npm install lottie-web
2.3 参数详解
调用lottie.loadAnimation()来启动动画。它接受一个对象作为唯一参数:
参数 | 含义 |
---|---|
container | 用于渲染动画的HTML元素,需确保在调用loadAnimation时该元素已存在 |
renderer | 渲染器,可选值为'svg'(默认值)/'canvas'/'html'。svg支持的功能最多,但html的性能更好且支持3d图层。各选项值支持的功能列表在此 |
loop | 默认值为true。可传递需要循环的特定次数 true / false / number |
autoplay | true/false 是否自动播放 ,一旦准备好,它就会开始播放 |
path | 动画对象的相对路径。与animationData 互斥,传入网络路径,如https://labs.nearpod.com/bodymovin/demo/markus/halloween/markus.json |
animationData | 带有导出动画数据的JSON数据,与path互斥,优先级更高,animationData为本地路径的json,需要import * as ** from "xx.json" |
name | 传递该参数后,可在之后通过lottie命令引用该动画实例 |
rendererSettings | 可传递给renderer实例的特定设置,具体可看 |
assetsPath | Json文件里资源的绝对路径 |
eg:
lottie.loadAnimation({
container: element, // the dom element that will contain the animation
renderer: 'svg',
loop: true,
autoplay: true,
path: 'data.json' // the path to the animation json
});
动画实例有以下主要方法:
- anim.play() :播放
- anim.stop() :停止
- anim.pause() :暂停
- anim.goToAndStop(value, isFrame) :第一个参数是一个数值。第二个参数是一个布尔值,为第一个参数定义时间或帧。可控制播放特定帧数。
- anm.setSpeed(speed) :可调节动画速度
查看更多内容
Lottie提供了用于监听动画执行情况的事件:
- complete
- loopComplete
- enterFrame
- segmentStart
- config_ready(初始配置完成)
- data_ready(所有动画数据加载完成)
- DOMLoaded(元素已添加到DOM节点)
- destroy
可使用addEventListener监听事件
// 动画播放完成触发
anm.addEventListener('complete', complete);
// 当前循环播放完成触发
anm.addEventListener('loopComplete', loopComplete);
// 播放一帧动画的时候触发
anm.addEventListener('enterFrame', enterFrame);
2.4 优缺点分析
lottie优点
Lottie方法方案是由设计师出动画,导出为json,给前端播放。所以,使用Lottie方案的好处在于:
- 动画由设计使用专业的动画制作工具Adobe After Effects来实现,使动画实现更加方便,动画效果也更好;
- 前端可以方便的调用动画,并对动画进行控制,减少前端动画工作量;
- 设计制作动画,前端展现动画,专业人做专业事,分工合理;
- 持跨平台,开发成本较低,一套Lottie动画可以在Android/IOS/Web多端使用;
- 使用lottie方案,性能好,除了解析json,基本没有其他耗性能的操作;并且相比于需要存储较多图片的帧动画,Lottie可以节省比较多的内存空间。
lottie不足
使用Lottie方案有以下不足之处:
- lottie-web文件本身仍然比较大,lottie.js大小为513k,轻量版压缩后也有144k,经过gzip后,大小为39k。所以,需要注意lottie-web的加载。目前H5项目有离线包,PC项目也会上PWA,会对其进行缓存,保证加载速度。
- lottie动画其实可以理解为svg动画/canvas动画,不能给已存在的html添加动画效果;
- 动画json文件的导出,目前是将AE里面的参数一一导出成json内容,如果设计师建了很多的图层,可能仍然有json文件比较大(20kb)的问题。需要设计师遵循一定的规范。
有很少量的AE动画效果,lottie无法实现,有些是因为性能问题,有些是没有做。比如:描边动画等。
2.5 其他
在线预览JSON动画网站:https://app.lottiefiles.com/preview
codepen在线链接:https://codepen.io/airnan
3.实现步骤
3.1 JSON文件的获取
注意:文中实现动画的json文件来自阿里巴巴矢量图标库
- 可以使用网络路径或本地路径
path: props.path,//网络路径
animationData: props.src,//本地路径,当二者同时实现优先级更高
- 文件中静态图片的处理, 将图片转换成base64编码,对json文件进行替换
图片在线转换base64编码
3.2使用lottie-web封装一个动画组件
<template>
<div ref="lottieBox"></div>
</template>
<script setup>
import lottie from "lottie-web";
import { onMounted, ref } from "vue";
const props = defineProps({
src: {
type: Object,
default: ()=>{},
},
path: {
type: String,
default: "",
},
loop: {
type: Boolean,
default: true,
},
autoplay: {
type: Boolean,
default: true,
},
});
const lottieBox = ref(null);
onMounted(() => {
if (lottieBox.value) {
const animation = lottie.loadAnimation({
container: lottieBox.value,
renderer: "svg", // 渲染方式:svg:支持交互、不会失帧、canvas、html:支持3D,支持交互
loop: props.loop, // 循环播放,默认:true
autoplay: props.autoplay, // 自动播放 ,默认true
path: props.path,//网络路径
animationData: Object.keys(props.src).length == 0 ? "" : props.src,//本地路径,优先级更高
});
}
});
</script>
3.3 实现一个lottie动画
- 引入组件与本地json路径:
import dataJson1 from "@/assets/json/data6.json";
import LottieAni from "@/components/lottie.vue";
<div class="ani-box">
<LottieAni :src="dataJson1" />
</div>
<div class="ani-box">
<LottieAni
path="https://labs.nearpod.com/bodymovin/demo/markus/halloween/markus.json"
/>
</div>
- 设置动画的样式
.ani-box {
width: 200px;
height: 300px;
border: 1px solid #ccc;
border-radius: 20px;
box-shadow: 0px 2px 2px 1px #abb3cf;
transition: all 0.5s;
margin-right: 30px;
margin-bottom: 30px;
display: flex;
align-items: center;
&:hover {
transform: scale(1.1);
}
}