Lottie - 设计和实现高性能动画效果

Lottie 介绍

Lottie 是 Airbnb 开源的一套跨平台的完整的动画效果解决方案,提供了专注于实现跨平台的高性能动画效果的 lottie-web、lottie-android、lottie-ios 产品,也提供了面向UI设计师和开发工程师的动画创作平台和其他创作平台的转化插件。

在 Lottie 出现之前,页面如果要展示酷炫的动画效果,开发者往往只能选择以下两种方式。

  • 动图
    设计师导出 GIF 等格式的动图,这类动图往往体积很大,加载体验差;其次难以控制,无法控制启动暂停时机,进而多多动画效果无法协作。
  • CSS实现
    开发者基于设计师提供Layer素材,利用 CSS 特效高仿出动画效果。这个是比较常见的,性能也能得到保证,但是无法实现复杂的动画效果,多动画效果之间的协作难以控制。
  • JavaScript 实现
    对于一些复杂的动画,开发者基于对动画的理解,采用 JavaScript 直接控制页面元素模拟动画效果,例如 Canvas、HTML 元素。这类实现往往是以牺牲性能为代价,无法跨平台使用,且实现及其复杂。

开发者和设计师迫切的需要一款产品,首先是将设计师视角下的动画效果(AE设计)转化成开发者能够使用的数据形式,降低沟通成本;其次是实现动画效果的高性能展示,并且提供一定程度的控制能力。

Lottie 就是在这种场景下应运而生的,设计师使用AE等设计工作设计出酷炫的效果,经过BodMoveIn插件导出 Json 文件,开发者根据业务需要填充业务数据,主要是更换素材,借助 lottie-web、lottie-android、lottie-ios 组件进行展示和控制动画效果。

Lottie 并不是一个最近出现的产品,业内也是一直在广泛的应用。近些年 Lottie 更多的是在动画创作方面做出的巨大的努力,一方面提供更多的转化插件,支持 AE、Figma、Sketch 等主流UE、UI设计产品的转换工具。

另外一方面则是设计了 Lottie Creator 的网页创作工具,支持开发者也能够自行设计酷炫的动画效果;

也提供了 LottieFiles 协作者平台,实现设计者之间的作品管理与共享;这些创新可以给我们带来意想不到的爽感,这也是本文重点向大家介绍的内容。

Lottie 使用

以 Lottie-web 为例,其使用十分简单。

初始化

php 复制代码
const anim = lottie.loadAnimation({
  // path: animJsonPath, // 动画json文件路径
  animationData: animationJSON,
  renderer: 'svg',
  loop: true,
  autoplay: true,
  container: lottieRef.current,
});

动画控制API

scss 复制代码
anim.play(); // 播放动画,从目前停止的帧开始播放
anim.stop(); // 停止播放动画,回到第0帧
anim.pause(); // 暂停动画,在当前帧停止并保持

anim.goToAndStop(value, isFrame); // 跳到某个时刻/帧并停止。isFrame(默认false)指示value表示帧还是时间(毫秒)
anim.goToAndPlay(value, isFrame); // 跳到某个时刻/帧并进行播放
anim.goToAndStop(20, true); // 跳转到第20帧并停止
anim.goToAndPlay(200); // 跳转到第200毫秒并播放

anim.playSegments(arr, forceFlag); // arr可以包含两个数字或者两个数字组成的数组,forceFlag表示是否立即强制播放该片段
anim.playSegments([10,30], false); // 播放完之前的片段,播放10-30帧
anim.playSegments([[0,10],[20,30]], true); // 直接播放0-10帧和20-30帧

anim.setSpeed(speed); // 设置播放速度,speed为1表示正常速度
anim.setDirection(direction); // 设置播放方向,1表示正向播放,-1表示反向播放
anim.destroy(); // 销毁动画,移除相应的元素标签等。在unmount的时候,需要调用该方法

常用事件

Lottie-web 还可以对动画的常规事件进行监听。

ini 复制代码
anim.addEventListener('DOMLoaded', () => {
  if (typeof callback === 'function') {
    callback(anim); // 处理动画内交互逻辑
  }
});

除了DOMLoaded事件,下面还有一些其他常用的事件可以监听:

  • complete: 播放完成(循环播放下不会触发)
  • loopComplete: 当前循环下播放(循环播放/非循环播放)结束时触发
  • enterFrame: 每进入一帧就会触发,播放时每一帧都会触发一次,stop 方法也会触发
  • segmentStart: 播放指定片段时触发,playSegments、resetSegments 等方法刚开始播放指定片段时会发出,如果 playSegments 播放多个片段,多个片段最开始都会触发。
  • data_ready: 动画 json 文件加载完毕触发
  • DOMLoaded: 动画相关的 dom 已经被添加到 html 后触发
  • destroy: 将在动画删除时触发

数据格式

当先很多动画效果并不是一成不变的,而是依据客户动态生成的。如果是要设计师为每个场景都设计一套效果数据,很明显是不显示的。好在 LottieData 是 JSON 格式的,只要能够理解其数据格式,开发者就可以自行调整一些动画效果,进行复用。

本文提供一个比较经典的动画效果-若干头像流星滑落的效果,JSON源文件-GitHub,动画效果请自行体验。

第一层数据结构主要是定义动画的整体控制信息。

json 复制代码
{
  "v": "5.6.7", // bodymovin 版本
  "fr": 30, // 帧率
  "ip": 0, // 起始关键帧
  "op": 736, // 结束关键帧
  "w": 612, // 视图宽
  "h": 198,  // 视图高
  "nm": "Avatars Lottie无蒙版", // 名称
  "ddd": 0, // 是否为3d
  "assets": [], // 资源集合 
  "layers": [], // 图层集合(包含动画中的每一个图层和动作信息)
  "markers": [], // 蒙层集合
}

这里 fr、ip、op、layers、assets是实际应用中可能需要关注的,特别是前 3 个尤为重要。

下面是图层数据格式,以复用为目标的场景下,只需要改动图层的部分数据和 assets 的部分资源信息即可,轨迹层面的改动需要关注 ks 图层变化属性,也是基于 CSS 效果来实现的,仅仅是描述语言不同,本质是一样的。

json 复制代码
"ddd": 0,                   // 是否为3d
"ind": 15,                  // layer的ID,唯一
"ty": 2,                    // 图层类型 
"nm": "light /新的.psd",    // 图层名称
"cl": "psd",
"parent": 32,
"refId": "image_0",
"sr": 1,
"ks": {                             //变换。对应AE中的变换设置

  "o": { "a": 0, "k": 100, "ix": 11 },     // 透明度
  "r": {...},                              // 旋转
  "p": {... },                             // 位置
  "a": {...},                              // 锚点
  "s": {                                   // scale 缩放
    "a": 1,
    "k": [
      {
        "i": { "x": [0.48, 0.48, 0.48], "y": [1, 1, 1] },
        "o": { "x": [0.26, 0.26, 0.26], "y": [1.01, 1.01, 0] },
        "t": 7,              // 代表关键帧数 (0-7帧 ,前后的变化)
        "s": [0, 0, 100],    // 代表变化前(图层为二维)。
        "e": [99, 99, 100]   // 代表变化后(图层为二维)。
      },
       {
        "i": { "x": [0.833, 0.833, 0.833], "y": [1, 1, 1] },
        "o": { "x": [0.167, 0.167, 0.167], "y": [0, 0, 0] },
        "t": 18,
        "s": [99, 99, 100],
        "e": [99, 99, 100]
      },
     ]
    },                             
},
shapes:[...],   //图层的宽高信息
"ao": 0,
"ip": 0,
"op": 150,
"st": 0,
"bm": 0

该数据格式相对于传统 Gif 格式,体积能够压缩到1/6,如上图所示,其新格式 dotLottie 在 JSON 的基础上再压缩到 1/6,数据体积大大降低。

渲染原理

LottieComposition 负责将 json 文件解析成数据对象, LottieDrawable 负责将 LottieComposition 解析的对象 绘制成 drawable 显示在 View 上。其底层绘制调用的是 Canvas 和 SVG 的API,这里就不详细介绍了。

LottieFiles 社区

LottieFiles 社区是最大的 Lottie 交流社区,主要服务于设计师和开发者,类似花瓣这类创作者网站。其本身属于其商业化的一部分,会有一些付费的功能和动画设计共享。对于我们开发者来说比较有用的部分是提供了 Lottie Creator 的动画效果网页编辑器,其使用比较傻瓜。这对于开发者是个福音,毕竟开发者对于 AE 等工具上手难度还是有的。

Lottie Creator 在线编辑器

上图是 Lottie Creator 的主要面板,且设计方式十分类似PPT的制作方式,其门槛并不高。开发者选择各种动效之后动画效果会自动拆解到每秒30帧,然后每帧进行微调。

我对这个编辑器的未来还是蛮看好的,当先就体验而言还是存在很多不足的,首先是性能问题,复杂效果之后卡顿明显;其次 AE Plugin 导出的 JSON 能够导入,但并不能编辑,大概率这个编辑器是个阉割版,无法支持复杂动画效果的编辑。

支持工具

数据转化

官网支持了 GIF、MP4、WebM、MOV 数据导出,虽然导出很慢,但是还是勉强能用。我推测其可能是采用的录制方式实现的,因此性能开销比较大。

调色板

支持对 SVG 素材进行微调色值,提供一系列调色板色系。

相关推荐
一斤代码1 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子1 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年1 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子2 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina2 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路3 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说3 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409193 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding3 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜3 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui