背景
在项目中,loading 常用的动画方案是 Gif 动画。
Gif 动画存在一些问题,例如:文件较大、无法缩放匹配不同屏幕大小和密度、易出现锯齿、无法控制动画等。
其他常用的动画方案有:
- Png 序列帧:文件大,可能会在不同屏幕分辨率下失真
- SVG 动画:实现成本高,易出现动画还原度低的情况
目前,项目需要经过调研,Lottie 动画是一种具有高可行性的方案。
Lottie 简介
Lottie 是 airbnb 开源的动画库,支持多个平台如 Android、iOS、Web、React Native 和 Windows。其提供从 AE 到各终端的完整工具流程。设计师可以通过 AE 的 Bodymovin 插件将动画导出为 json 文件
,然后通过 Lottie 实现动画效果
,确保动画的还原度
。
lottie实现的动画效果:
lottie-web
lottie-web 支持多种特性,提供复杂的动画控制和监听功能。
使用示例如下:
lottie.loadAnimation({
container: animationWindow,
renderer: 'svg',
loop: true,
autoplay: true,
path: 'https://linwu-hi.github.io/lottie/animation_ll2ddfyg.json'
});
控制动画播放的方法:
名称 | 描述 |
---|---|
animation.play | 播放该动画,从目前停止的帧开始播放 |
stop | 停止播放该动画,回到第 0 帧 |
pause | 暂停该动画,在当前帧停止并保持 |
goToAndStop | animation.goToAndStop(value, isFrame);跳到某个时刻/帧并停止。isFrame(默认 false)指示 value 表示帧还是时间(毫秒) |
goToAndPlay | animation.goToAndPlay(value, isFrame);跳到某个时刻/帧并进行播放 |
goToAndStop | animation.goToAndStop(30, true);跳转到第 30 帧并停止 |
playSegments | animation.playSegments(arr, forceFlag);arr 可以包含两个数字或者两个数字组成的数组,forceFlag 表示是否立即强制播放该片段 animation.playSegments([10,20], false);播放完之前的片段,播放 10-20 帧 animation.playSegments([[0,5],[10,18]], true);直接播放 0-5 帧和 10-18 帧 |
setSpeed | animation.setSpeed(speed);设置播放速度,speed 为 1 表示正常速度 |
setDirection | animation.setDirection(direction);设置播放方向,1 表示正向播放,-1 表示反向播放 |
destroy | animation.destroy();删除该动画,移除相应的元素标签等。在 unmount 的时候,需要调用该方法 |
监听事件:
名称 | 描述 |
---|---|
data_ready | 加载完 json 动画 |
complete | 播放完成(循环播放下不会触发) |
loopComplete | 当前循环下播放(循环播放/非循环播放)结束时触发 |
enterFrame | 每进入一帧就会触发,播放时每一帧都会触发一次,stop 方法也会触发 |
segmentStart | 每进入一帧就会触发,播放时每一帧都会触发一次,stop 方法也会触发 |
DOMLoaded | 动画相关的 dom 已经被添加到 html 后触发 |
destroy | 将在动画删除时触发 |
Lottie 动画性能
对比 Lottie 和 Gif 动画,数据显示 Lottie 动画文件更小,帧率更高,而且其性能表现更好。
- GIF动图
- Lottie动画

react-lottie
react-lottie 将 lottie-web 封装成 React 组件,使其更加易于在 React 中使用。
import React from 'react'
import Lottie from 'react-lottie';
import * as animationData from './pinjump.json'
export default class LottieControl extends React.Component {
constructor(props) {
super(props);
this.state = {isStopped: false, isPaused: false};
}
render() {
const buttonStyle = {
display: 'block',
margin: '10px auto'
};
const defaultOptions = {
loop: true,
autoplay: true,
animationData: animationData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
};
return <div>
<Lottie options={defaultOptions}
height={400}
width={400}
isStopped={this.state.isStopped}
isPaused={this.state.isPaused}/>
<button style={buttonStyle} onClick={() => this.setState({isStopped: true})}>stop</button>
<button style={buttonStyle} onClick={() => this.setState({isStopped: false})}>play</button>
<button style={buttonStyle} onClick={() => this.setState({isPaused: !this.state.isPaused})}>pause</button>
</div>
}
}
vue-lottie
vue-lottie 将 lottie-web 封装成 vue 组件,使其更加易于在 vue 中使用。
也有vue3-lottie
<template>
<div id="app">
<lottie :options="defaultOptions" :height="400" :width="400" v-on:animCreated="handleAnimation"/>
<div>
<p>Speed: x{{animationSpeed}}</p>
<input type="range" value="1" min="0" max="3" step="0.5"
v-on:change="onSpeedChange" v-model="animationSpeed">
</div>
<button v-on:click="stop">stop</button>
<button v-on:click="pause">pause</button>
<button v-on:click="play">play</button>
</div>
</template>
<script>
import Lottie from './lottie.vue';
import * as animationData from './assets/pinjump.json';
export default {
name: 'app',
components: {
'lottie': Lottie
},
data() {
return {
defaultOptions: {animationData: animationData},
animationSpeed: 1
}
},
methods: {
handleAnimation: function (anim) {
this.anim = anim;
},
stop: function () {
this.anim.stop();
},
play: function () {
this.anim.play();
},
pause: function () {
this.anim.pause();
},
onSpeedChange: function () {
this.anim.setSpeed(this.animationSpeed);
}
}
}
</script>
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END