阅读时间 10~15minjavascript
项目中为了优化用户体验加入了几处微交互动画,过时的流程都是设计输出合成的雪碧图,前端经过序列帧实现动画效果,以下图动画效果:css
序列帧:html
动画效果:前端
序列帧:vue
帧动画的缺点和局限性比较明显,合成的雪碧图文件大,且在不一样屏幕分辨率下可能会失真。经调研发现,Lottie是个简单、高效且性能高的动画方案。java
Lottie是可应用于Android, iOS, Web和Windows的库,经过Bodymovin解析AE动画,并导出可在移动端和web端渲染动画的json文件。换言之,设计师用AE把动画效果作出来,再用Bodymovin导出相应地json文件给到前端,前端使用Lottie库就能够实现动画效果。node
关闭AEgit
下载并安装ZXP installergithub
下载最新版bodymovin插件
github.com/airbnb/lott…
把下载好的bodymovin.zxp拖到ZXP installer
打开AE,在菜单首选项->常规中勾选:ballot_box_with_check:容许脚本写入文件和访问网络(不然输出JSON文件时会失败)
在AE中制做动画,打开菜单窗口->拓展->Bodymovin,勾选要输出的动画,并设置输出文件目录,点击render
打开输出目录会看到生成的JSON文件,若动画里导入了外部图片,则会在images中存放JSON中引用的图片
静态URL
cdnjs.com/libraries/l…
NPM
npm install lottie-web
复制代码
调用loadAnimation
lottie.loadAnimation({
container: element,
renderer: 'svg',
loop: true,
autoplay: true,
path: 'data.json'
});
复制代码
也能够在vue中使用lottie
import lottie from '../lib/lottie';
import * as favAnmData from '../../raw/fav.json';
export default {
props: {
options: {
type: Object,
required: true
},
height: Number,
width: Number,
},
data () {
return {
style: {
width: this.width ? `${this.width}px` : '100%',
height: this.height ? `${this.height}px` : '100%',
overflow: 'hidden',
margin: '0 auto'
}
}
},
mounted () {
this.anim = lottie.loadAnimation({
container: this.$refs.lavContainer,
renderer: 'svg',
loop: this.options.loop !== false,
autoplay: this.options.autoplay !== false,
animationData: favAnmData,
assetsPath: this.options.assetsPath,
rendererSettings: this.options.rendererSettings
}
);
this.$emit('animCreated', this.anim)
}
}
复制代码
container
用于渲染动画的HTML元素,需确保在调用loadAnimation时该元素已存在
renderer
渲染器,可选值为'svg'(默认值)/'canvas'/'html'。svg支持的功能最多,但html的性能更好且支持3d图层。各选项值支持的功能列表在此
loop
默认值为true。可传递须要循环的特定次数
autoplay
自动播放
path
JSON文件路径
animationData
JSON数据,与path互斥
name
传递该参数后,可在以后经过lottie引用该动画实例
rendererSettings
可传递给renderer实例的特定设置,具体可看
Lottie提供了用于监听动画执行状况的事件:
可以使用addEventListener监听事件
// 动画播放完成触发
anm.addEventListener('complete', anmLoaded);
// 当前循环播放完成触发
anm.addEventListener('loopComplete', anmComplete);
// 播放一帧动画的时候触发
anm.addEventListener('enterFrame', enterFrame);
复制代码
可以使用anm.pause和anm.play暂停和播放动画,调用anm.stop则会中止动画播放并回到动画第一帧的画面。
使用anm.setSpeed(speed)可调节动画速度,而anm.goToAndStop(value, isFrame)和anm.goToAndPlay可控制播放特定帧数,也可结合anm.totalFrames控制进度百分比,好比可传anm.totalFrames - 1跳到最后一帧。
anm.goToAndStop(anm.totalFrames - 1, 1);
复制代码
这样的好处是能够把相关联的JSON文件合并,经过anm.goToAndPlay控制动画状态的切换,以下图例中一个JSON文件包含了2个动画状态的数据:
JSON文件里assets设置了对图片的引用:
若想统一修改静态资源路径或者设置成绝对路径,可在调用loadAnimation时传入assetsPath参数:
lottie.loadAnimation({
container: element,
renderer: 'svg',
path: 'data.json',
assetsPath: 'URL’ // 静态资源绝对路径
});
复制代码
即便用bodymovin成功输出了JSON文件(没有报错),也会出现动效不如预期的状况,好比这是在AE中构建的形象图:
但在页面中渲染效果是这样的:
这是由于使用了不支持的Merge Paths功能
所以对设计师而言,建立Lottie动画和往常制做AE动画有所不一样,此文档记录了Bodymovin支持输出的AE功能列表,动画制做前需跟设计师沟通好,根据动画加载平台来确承认使用的AE功能。
因为以上所说的功能支持问题会致使输出动画效果不肯定性,设计师和前端之间有个动画效果联调的过程,为了提升联调效率,设计师可先进行初步的效果预览,再把文件交付给前端。
渲染前设置所要渲染的文件
勾选☑️Demo选项
在输出的文件目录中就可找到可预览的demo.html文件
把生成的JSON文件传到LottieFiles平台,可播放、暂停生成文件的动画效果,可设置图层颜色、动画速度,也能够下载lottie preview客户端在iOS或Android机子上预览。
LottieFiles平台还提供了不少线上公开的Lottie动画效果,可直接下载JSON文件使用
Lottie的不足之处是没有对应的API操纵动画层,若想作更细化的动画处理,只能直接操做节点来实现。好比当播放完左图动画进入惊讶状态后,若想实现右图随鼠标移动而控制动画层的简单效果:
开启调试面板能够看到,lottie-web经过使用
当元素已添加到DOM节点,找到想要控制的
onIntroDone() {
const Gs = this.refs.svg.querySelectorAll('svg > g > g > g');
Gs.forEach((node, i) => {
// 过滤须要修改的节点
...
// 获取transform属性值
const styleArr = node.getAttribute('transform').split(',');
styleArr[0] = styleArr[0].replace('matrix(', '');
styleArr[5] = styleArr[5].replace(')', '');
const style = `matrix(${styleArr[0]}, ${styleArr[1]}, ${styleArr[2]}, ${styleArr[3]}, ${styleArr[4]}, ${styleArr[5]})`;
// 使用Rematrix解析
const transform = Rematrix.parse(style);
this.matrices.push({
node,
transform,
prevTransform: transform
});
}
}
复制代码
监听鼠标移动,设置新的transform属性值。
onMouseMove = (e) => {
this.mouseCoords.x = e.clientX || e.pageX;
this.mouseCoords.y = e.clientY || e.pageY;
let x = this.mouseCoords.x - (this.props.browser.width / 2);
let y = this.mouseCoords.y - (this.props.browser.height / 2);
const diffX = (this.mouseCoords.prevX - x);
const diffY = (this.mouseCoords.prevY - y);
this.mouseCoords.prevX = x;
this.mouseCoords.prevY = y;
this.matrices.forEach((matrix, i) => {
let translate = Rematrix.translate(diffX, diffY);
const product = [matrix.prevTransform, translate].reduce(Rematrix.multiply);
const css = `matrix(${product[0]}, ${product[1]}, ${product[4]}, ${product[5]}, ${product[12]}, ${product[13]})`;
matrix.prevTransform = product;
matrix.node.setAttribute('transform', css);
})
}
复制代码
看到一个方法,在AE中将图层命名为**#id格式,生成的SVG相应的图层id会被设置为id**,命名为**.class格式,相应的图层class会被设置为class**
试了下的确能够,以下图,所以可经过这个方法快速找到须要操做的动画层,进一步简化代码:
Lottie的缺点在于若在AE动画制做的过程不注意规范,会致使数据文件大、耗内存和性能的问题;Lottie-web的官方文档不够详尽,例如assetsPath参数是在看源码的时候发现的;开放的API不够齐全,没法很灵活地控制动画层。
而优势也很明显,Lottie能帮助提升开发效率,精简代码,易于调试和维护;资源文件小,输出动画效果保真;跨平台——Android, iOS, Web和Windows通用。
总的来讲,Lottie的引用能够替代传统的GIF和帧动画,灵活利用好提供的属性和方法能够控制动画的播放,但需注意规范设计和开发的流程,才能够更高效地完成动画的制做与调试。
关注公众号:【IVWEB社区】,每周推送精品技术周刊 。