01. Lottie 的播放控制 API
Lottie 最大的特点是提供了一系列 API 来控制动画播放,从官方文档可以看到这几个主要 API
- play()
- playSegments()
- pause() / resume()
- setSpeed()
除了一看就懂的开始、暂停、调整播放速度之外,有一个奇妙的 playSegments 方法,它可以指定只播放 Lottie 动画中的一小段
animation
- 第一个参数是数组,指定了播放帧区间,比如上面例子指从第 10 帧播放到第 20 帧
- 第二个参数表示是否强制播放,如果当前 lottie 动画已经在播放的话,这个参数设为 true 可以先强制停止之前的动画后,再播放指定的帧区间
别小看这么简单一个 API,正是通过它我们才能实现各种复杂的业务
02. 简单例子
找一个简单的例子看下,这里有一个来自社区 lottie 文件 , 一共 240 帧,可以看到动画中有多种车型的 loading
- 0~36 帧是小汽车
- 37~72 帧是跑车
- ……
- 180~206 是公交车
- ……
现在如果只需要播放公交车那段 loading 的话,用 playSegments 很容易实现
const
这里有几个常见坑点
- 记得在 lottie 动画 DOMLoaded 之后再调用 playSegments,否则会播放完整段动画后才播放片段,这可以说是 lottie 实现的一个小 bug,但也是新手最常遇到的问题
- 动画是否循环由初始化动画时的 loop 属性决定,如果初始化时设为 false,那么 playSegements 的片段只会播放一遍
- 可以在播放前通过 animation.loop = true 再设置,不过这个属性不见于官方文档
实际效果是这样
代码参考
03. 复杂例子
如果只是这么简单的例子,那全文就到此结束啦,下面看个复杂的例子,上一篇文章中有一个掷骰子的动画
这段 Lottie 其实长这样
- 0~25 帧是骰子从左下角抛出
- 26~35 帧是骰子在空中旋转
- 36~39 帧是骰子 1 点(一共 4 帧)
- 40~43 帧是骰子 2 点(一共 4 帧)
- ……
做过营销页的前端都知道,这里通常会伴随着一个 ajax 请求去获取应该掷出几点,大致流程是
- 发起 ajax 请求,同时播放骰子 掷出的动画
- ajax 请求返回后,播放相应点数的动画
代码撸起
btn
这样一下就看出 lottie 的潜力了,不仅仅是播放动画那么简单,还能结合业务实现一些逻辑呢!
上面的实现看起来很简单,但是仔细思考一下就会发现不少问题
- ajax 如果耗时很短,那么骰子刚抛出一半就展示结果,体验不太好(其实是太假了 )
- ajax 如果耗时很长,那么就更尴尬了,要么一直 loop 播放骰子抛出来,要么动画停在原地不动
可以查看这段代码感受一下
03.1 体验优化
仔细思考下体验的优化,其实需要对动画+异步 ajax 做比较精细的操作,如下
- 并发骰子抛出 + ajax 请求
- 保证骰子抛出 + 空中旋转至少播放一次,之后再展示点数,应对 ajax 耗时短的情况
- 空中旋转可以循环播放,应对 ajax 耗时长的情况
为了实现这个上面的效果,我们需要感知一段动画播放结束,这在 lottie 中有 complete 事件
先简单尝试下,在筛子动画播放完成后再展示点数
animation
这里可以发现,通过事件监听方式来做会比较麻烦,需要设置不少临时的中间变量,另外以上代码离最终目标还有不少差距,比如没实现循环播放
04. 优雅地控制播放
那么如何优雅地写出复杂的播放控制代码呢?
仔细思考一下,这个案例本质上是异步流的控制,于是我们可以引入 Promise
首先将播放动画这个过程,封装为 Promise
function
这里用到一个 lottie 文档未说明的技巧,addEventListener 的返回值是一个函数,用于移除事件监听
基于上面这个 Promise 封装,结合 async/await 很多场景的代码就变得优雅多了
比如,先后播放两段动画,并且在播放完成之后做一些事情
await
不满足条件时,一直循环播放某一段动画,这样就不依赖于初始化动画时的 loop 参数了
while
ajax 与动画同时发生,当动画播放完毕,并且 ajax 返回时进入下一个环节
const
04.1 完整实现
于是再回到上面的例子,我们可以写出优雅的播放控制代码了
// 播放掷骰子的动画
完整代码参考
04.2 小结
通过 lottie 事件,将动画播放过程封装为 Promise 之后,就可以对接进入各种异步流管理中了,不论是顺序、并发还是上面更复杂的例子,代码写起来都很优雅,适合纳入最佳实践
最后是下篇预告: