在我们大大小小的项目里,基本上gif、png序列帧、svg动画占据了比较大的一部分,很多情况下我们都忽略了他们本身的一部分缺点。因此对于如何让动画有一个新的实现方式有了兴趣,lottie便步入我的视野。
GiF、PNG、SVG动画
Gif :
- 优点:Gif 广泛支持 Internet 标准。支持无损耗压缩和透明度。
- 缺点:Gif 文件一般较大,大小固定,无法缩放以匹配大屏幕和高密度屏幕,容易有锯齿,不能控制,只支持 256 色调色板,对动画画质要求高则无法满足,也不能交互,会引起重绘。
Png :
优点:写法简单,可以使用css动画,js去操作,实现周期短,出图快。
缺点:若是合成雪碧图,会产生文件大,且在不同屏幕分辨率下可能会失真的问题,若是动态替换src地址,则会触发多次资源请求,浪费更大。
Svg :
优点:矢量图形,不受像素影响
缺点:实现成本高,容易出现动画还原度低的情况
lottie
1、介绍
Lottie是 airbnb 开源的可应用于Android,iOS,Web,React Native和Windows动画库, 本质上是一套跨平台的动画解决方案。它提供了一套完整的从 AE 到各个终端的工具流,通过 AE 的 Bodymovin 插件将设计师做的动画导出成一套定义好的 json 文件,之后再通过 Lottie 各端的库就可以实现动画效果。
2、lottie-web
ps:作为一个前段开发,在此先介绍下lottie-web
1、安装
npm install lottie-web
2、调用
import lottie from 'lottie-web';
const dataJson = require('data.json');
let animation = lottie.loadAnimation({
container: Ele,
renderer: 'svg',
loop: true,
autoplay: true,
animationData: dataJson,
assetsPath: url,
});
3、属性
animation.play(); // 从目前停止的帧开始播放
animation.stop(); // 停止播放,回到第0帧
animation.pause(); // 暂停该动画,在当前帧停止并保持
animation.goToAndStop(value, isFrame); // 跳到某个时刻/帧并停止。isFrame(默认false)指示value表示帧还是时间(毫秒)
animation.goToAndPlay(value, isFrame); // 跳到某个时刻/帧并进行播放
animation.goToAndStop(30, true); // 跳转到第30帧并停止
animation.goToAndPlay(300); // 跳转到第300毫秒并播放
animation.playSegments(arr, forceFlag); // arr可以包含两个数字或者两个数字组成的数组,forceFlag表示是否立即强制播放该片段
animation.playSegments([10,20], false); // 播放完之前的片段,播放10-20帧
animation.playSegments([[0,5],[10,18]], true); // 直接播放0-5帧和10-18帧
animation.setSpeed(speed); // 设置播放速度,speed为1表示正常速度
animation.setDirection(direction); // 设置播放方向,1表示正向播放,-1表示反向播放
animation.destroy(); // 删除该动画,移除相应的元素标签等。在unmount的时候,需要调用该方法
4、事件
* data_ready:数据准备完成
* complete: 播放完成(循环播放下不会触发)
* loopComplete: 当前循环下播放(循环播放/非循环播放)结束时触发
* enterFrame: 每进入一帧就会触发,播放时每一帧都会触发一次,stop方法也会触发
* segmentStart: 播放指定片段时触发,playSegments、resetSegments等方法刚开始播放指定片段时会发出,如果playSegments播放多个片段,多个片段最开始都会触发。
* data_ready: 动画json文件加载完毕触发
* DOMLoaded: 动画相关的dom已经被添加到html后触发
* destroy: 将在动画删除时触发
5、注意
- 描边动效不支持,会导致性能问题,web不支持
- 图层越多,json数据越大
- 导出的图层以#svgId命名,可以通过Id获取;导出以.svgClass命名,可以通过Class获取
3、封装lottie-web组件,在Vue或React使用
Vue
<.template>
<.div :style="styles" ref="lottieEl"><./div>
<./template>
import lottie from 'lottie-web'
export default {
props: {
options: {
type: Object,
required: true
},
styles:{
type:Object,
default:()=>{
return {
width: '80px',
height: '80px',
}
}
},
json:{
type: Object,
required: true
}
},
data() {
return {
lottie:{},
}
},
mounted() {
this.lottie = lottie.loadAnimation({
container: this.$refs.lottieEl,
renderer: 'svg',
loop: this.options.loop ? true : false,
autoplay: this.options.autoplay ? true : false,
animationData: this.json,
})
}
}
<./script>
React
import React from 'react'
import Lottie from 'react-lottie';
import * as jsonData from './data.json'
export default class LottieWrapper 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: jsonData,
};
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 style={buttonStyle} onClick={() => this.setState({isStopped: false})}>play
<.button style={buttonStyle} onClick={() => this.setState({isPaused: !this.state.isPaused})}>pause
<./div>
}
}
ps:由于编辑器插件Bug会渲染标签,运行时请去除标签前面的点号
Comments | 1 条评论
该评论为私密评论