iOS 的动画实现早已不是什么新鲜话题。
相信很多 iOS 开发不但熟练掌握了动画的使用方法,很多甚至深入到底层实现。
当然,本文的重点并不是介绍 iOS 的动画 API 如何使用,而是想简单聊一下对于复杂动画框架的选择侧重。
动画的分类
这里我将 iOS 中动画的种类以 API
调用的方式分为四类, 对 iOS 底层动画实现的机制讲解并不是本文的重点,如果有同学对这块感兴趣,网上都很多资料可供参考。例如这一篇就讲的不错.
关于iOS动画底层的实现:https://lision.me/ios-rendering-process/
-
基于 UIView 的动画:即主要以修改 UIView 属性来实现的的一些动画, 例如
UIView.animation
相关的一系列 API。主要实现的动画效果常见的有 位移
大小
transform
颜色变换
Layer 层的动画:以官方的
CABasicAnimation
和 facebook 的pop
为主。Layer 层的动画的表现力强于 UIView 动画
能够实现复杂的 keyframe animation
有 CALayer 有 3DTransformation,所以可以用 layer 层动画做 3D 动画。
-
特别是 pop,他在 SpringAnimation 中提供了
dynamicsTension
和dynamicsMass
两个属性,所以可以和很多工具无缝衔接,例如Principle
-
可交互动画类型:UIViewPropertyAnimator
这类动画天然支持和手势的交互,例如
continueAnimation
等方法, 当然,除了UIView.animation
完全不支持交互式动画以外,其实 CABasicAnimation 也可以利用layerSpeed
和timeOffset
等方法组合起来配合手势实现交互式动画,不过难度和繁琐程度有尝试过的开发应该能感受到。PropertyAnimator 可以视为 UIView.animation 的 API 优化版和功能增强版,对于组合动画,交互式动画等,在设计上的方便程度和易用程度的提升是革命性的。
Gif 类动画
此类动画本质是播放序列帧。
很多第三方库可以支持,例如 YYImage 和 FLAnimateImage
gif 动画最大的问题是大小和质量,因为 gif 本质是多张图片的组合播放,所以一旦动画时长超过 10s, 分辨率较高,gif 的大小就直奔 5mb 以上去了。
gif 动画的性能也是比较大的问题,有兴趣的同学可以测试一下同屏多个 gif 渲染,手机帧率会下降到什么程度
所以除了在表情包市场的少量领域,几乎没有人用 gif 来实现 app 里的动画。
即便是表情包市场,也普遍以 SVG 或者 mp4 格式代替了。
非人力可为的复杂动画
当然,上述的三种动画尚能称之为人力可为。什么意思呢?
指的是,程序员对于上述动画依旧能够利用足够的耐心和反复的尝试来拆解和实现。但是,下面我要说的这类动画,不依靠设计工具纯靠编程是几乎无法实现的。比如下面这个
即便抛去复杂动画难以通过手撸代码来实现这一现实问题。还有一点不可忽视的原因是,原生代码实现动画的成本之高也到了难以忍受的程度了。
从设计动画到多端实现,从 iOS 到 Android 到 RN 甚至 flutter,一套动画如果采取原生实现的话,需要写 4 套代码。这成本是绝对不可接受的。因此,lottie 和 pag 也应运而生了。
Lottie VS PAG
lottie 相信大家并不模式,是 airbnb 针对复杂动画场景研发的框架,包含多个端和一个 ae 插件 bodymovin 来导出动画。
pag 相对而言可能陌生一点,pag 是腾讯新推出的一款完整的动画工作流。提供从AE(Adobe After Effects)导出插件,到桌面预览工具,再到各端的跨平台渲染 SDK。
至于为什么会调研两个框架,则是由于我最近要开发一款表情和礼物特效的 UI 框架,所以需要调研市面上能够实现复杂动效的框架,所以我针对这两个 SDK 做了一些研究和比较。
在对比两个框架之前,我们需要先介绍一下,lottie 和 pag 的工作原理到底是什么,他们又是怎么在端上实现复杂动画的。
我们先来看一下使用 lottie 的简单流程。
pag 的流程。
从两个框架的流程图可以看出,工作流大体相似,如
由 AE 生成动画
附带 AE 插件,可以通过插件导出动画
lottie 的 bodymovin
PAG 的 PAGViewer
预览
导出文件
端上的渲染 SDK
框架的比较
对于一个成熟项目而言,选择一个框架是需要非常谨慎的。
考虑到接入到项目之后,框架会伴随着项目的发展和演进,所以我们需要从多个维度来看,到底哪个适合,或者说哪个更好。
我主要从下列几个维度进行了比较。
AE 插件能力
插件能力代表了这两个框架能够使用多少 AE 的功能,也即意味着功能的多寡。
我根据两个框架公开的信息对比了一下。
- PAG 插件能力列表: https://pag.io/docs/ae-support.html
- lottie 插件能力列表: https://aescripts.com/bodymovin/
结论大概如下:Lottie和SVGA都使用AE Script SDK来导出AE工程,但是AE Script SDK本身存在一定限制,不能访问AE文件中的所有属性,PAG则使用AE C++ SDK,能访问AE文件中所有属性和一些高级API,能够实现对AE文件的完整导出。
导出文件
导出文件的选择上,lottie 选择了 JSON, PAG 采用了类似于 protocolbuffer 的二进制文件来实现。
二者比较我觉的能力上各有优劣。
lottie 采用 JSON 可读性强,但是承载AE特性能力差,文件体积大,解码速度慢。
PAG采用二进制的编码方法,优势大概有:
- 自研编解码器
- 动态比特位压缩,冗余信息极少,文件体积小,解码速度快
- 支持图片和音频信息编码。
不过基于插件导出文件而言,我不认为会有人去人肉读取 bodymovin 导出的 JSON 文件去修改。
所以这一点上我认为 PAG 的做法更有优势。
SDK 的实现
- lottie 基于各端的 native 来实现
- PAG 基于 C++ ,在端上进行了抹平。
基于各端的 native 的渲染其实渲染一致性上会是一个问题,比如 RN 相对于 Flutter是一个很好地对照例子。一个是代码转译,一个是自研渲染引擎 skia, 所以 Flutter 的表现力上要比 RN 这种依赖端上的框架强很多。所以我认为 C++ 作为不同端的统一渲染是一种更好的方法。
跨平台的支持
平台支持 | lottie | PAG |
---|---|---|
Android | ✅ | ✅ |
iOS | ✅ | ✅ |
Web | ✅ | ✅ |
mac OS | ✅ | ✅ |
Linux | ❌ | ✅ |
Windows | ❌ | ✅ |
端上的支持 PAG 更丰富一些,也是依托于底层采用 C++的实现,抹平了端上的差异,所以支持的平台更多。
性能
性能我认为是复杂动画框架最重要的一环,特别是移动端上同屏多动画渲染的性能,其实直接决定了 SDK 的使用与否。我认为在性能的比对上,其实存在一票否决的能力。
根据我能搜到的信息,我把两个框架的性能 PK 相关信息摘录了一下。
矢量动画文件对比
矢量动画渲染性能
结论
经过一些调研,和我实际下载体验了两个框架,我觉得在工具,插件,底层实现和渲染, PAG 对我而言是更好的一个动画框架。
当然,每个人面对的项目和情况不同,本文仅做参考。也希望有人能够在更多层面进行比对,提出不同方向的反馈。
关于两个框架更多实现的细节,也可以参考我上面发的链接地址。