lottie

是什么?

  • 是airbnb出产的一款动效插件,现在支持开发侧的web/RN/Android/ios/Mac os,以及设计侧的AE。
  • web端的文档地址:Web - Lottie Docs

    为什么要用?

  • web端动效的方式有几种:

    • 给静图(jpg/jpeg/png/svg),通过设计口述或者作出动图,开发手写css/canvas来实现。
      • 优势:灵活,所有动效都尽在开发的掌握。
      • 劣势:开发时间长,沟通成本大,设计同学很难空口描述出想要的动效,也受开发的水平限制比较大。
    • 给gif,开发用图片的形式嵌入。
      • 优势:开发成本低,沟通成本小。
      • 劣势:gif一般都比较大,比较小的噪点又过于明显,性能的性价比不高;只能循环播放,较为死板。
    • 雪碧图序列帧,给一个合成的雪碧图(静图),开发通过序列帧的方式进行动效操作。
      • 优势:开发成本中等,沟通成本小。
      • 劣势:合成的雪碧图文件大,且在不同屏幕分辨率下可能会失真。
    • 使用lottie,设计同学给出json文件和图片文件夹,开发同学引入lottie插件,对json进行解析。
      • 优势:开发成本中等,效果不受开发同学水平限制,只要设计画的出,开发就能实现出来;灵活,基点元素可以作为一个普通的dom节点进行定位,整个动画可以任意播放停止甚至倒放以及从某一帧开始播放(具体能实现的参见api文档),灵活度非常高。
      • 劣势:在开发层面和设计层面看到的帧节点以及播放速度不同,需要持续进行沟通联调,沟通成本大;lottie插件打包前400+kb,打包后也有200+kb,会显著增加项目的大小。
    • 使用svga,设计同学给出.svga文件,开发引入svga插件,对其进行解析。
      • 优势:理论上来说同lottie
      • 劣势:实际引入中,该插件已5个月没有更新代码,并且现存版本存在“无故清除canvas画布”的问题,不稳定性极高,不建议使用。
  • 几相对比下来,对于放在“主交互游戏”类活动页里的动效,lottie目前是最好的方案。

    怎么用?

    (建议使用npm引入,减少基础组件对网络的依赖)
  1. // 项目目录运行
  2. cnpm install lottie-web --save-dev
  1. // 引入lottie
  2. import lottie from 'lottie-web'
  3. Vue.prototype.$lottie = lottie
  4. // 加载动画(遵从vue声明周期,这个调用需在dom节点加载出来,也即是mount之后)
  5. // 此处以扭蛋的 加载机器日常状态动画 为例
  6. let machineNormal = document.querySelector('#machineNormal')
  7. this.normalAni = this.$lottie.loadAnimation({
  8. container: machineNormal, // the dom element
  9. renderer: 'canvas',
  10. loop: true,
  11. autoplay: true,
  12. path: 'static/machine_normal.json', // the animation data
  13. })

使用lottie的过程中,需要注意什么?

引入过程中

  1. lottie动画加载需要一个dom节点,这个dom节点可被任意操纵位置,动画加载完毕后整个dom的宽高会被填充为动画的宽高,也即是设计给出的动画过程中最宽、最高的那个数值。
  2. 同样因为lottie动画加载需要一个dom节点,所以加载动画的方法需在mount周期或者之后调用。
  3. 如果使用path参数引入json文件:

文件放在本地:

  1. 1. 图片也需放在本地,通过修改.json文件的assets里面每一项的u属性,可以自定义图片文件夹的名字。

例如:

  1. {
  2. "v": "5.5.8",
  3. "fr": 24,
  4. "ip": 1,
  5. "op": 53,
  6. "w": 662,
  7. "h": 827,
  8. "nm": "",
  9. "ddd": 0,
  10. "assets": [
  11. {
  12. "id": "image_0",
  13. "w": 662,
  14. "h": 827,
  15. "u": "machine_img/", /* 这个就是文件夹的名字 */
  16. "p": "img_0.png",
  17. "e": 0
  18. },
  19. ]
  20. }

ii. 建议使用static文件夹存放,不受到打包的影响。
update如果使用的是vue-cli 3,那么放在public文件夹下,并且path直接写想要的文件名,例如:

  1. this.lottie = this.$lottie.loadAnimation({
  2. container: document.querySelector('#BindDom'), // the dom element that will contain the animation
  3. renderer: 'svg',
  4. loop: true,
  5. autoplay: true,
  6. path: 'data.json' // the path to the animation json
  7. })


文件放在cdn:**
注意图片的文件夹应该与json文件放在同一目录下,例如:

  1. /twist_egg/btn_gain.json
  2. /twist_egg/btn_gain_img/img_0.png

动画运行过程中

  1. 在动画初始化的时候,lottie提供生命周期以感知动画的加载状态,主要提供以下几种:
    • complete
    • loopComplete
    • enterFrame
    • segmentStart
    • config_ready (when initial config is done)
    • data_ready (when all parts of the animation have been loaded)
    • DOMLoaded (when elements have been added to the DOM)
    • destroy

其中DOMLoaded理论上是最晚能感知到的周期,也即是“动画加载完成”。但实际使用下来,只有使用canvas形式加载动效的时候,这个事件才是所有图片全部加载完成;其余情况(svg,html),都只是“开始拉取图片”,还是会展示给用户图片加载的整个过程。
并且,即使使用canvas加载,如果json文件与对应的图片文件夹都是云端也就是cdn的形式拉取的话,依旧无法感知到所有图片加载的过程。所以如果有强需求,需要用户完全不感知图片加载,建议将文件放在本地并以canvas形式加载。

  1. lottie提供destroy的api以清空画布,但是在destroy旧动画 -> load新动画这个过程中,会有非常明显的全屏闪动,这是由于画布重新生成需要时间造成的,建议使用dom的显隐切换而不是画布的destroy来切换同一块动效的不同状态。
  2. 可任意使用onComplete的事件监听,不会发生事件的重新绑定。
  3. lottie不提供原生的缓停事件,但是可以通过提供的setSpeed方法进行多段调整速度,已达到缓停的效果。