移动端帧动画神来之笔 Lottie (iOS:从Json到Animation)

Lottie 简介

Lottie刚出来两个月的时候,我们正好想寻找一个可扩展的方案支持项目的2D帧动画需求,同事介绍下调研了Lottie。看官网Demo里各种酷炫的矢量动画,瞬间被惊艳到。想象一下平时写复杂动画的痛苦: 一堆hard code, 被设计师各种追着调参数看效果。还有更复杂的平面动画,可能就直接上GIF,可使用 Gif 占用空间较大,而且需要为各种屏幕尺寸、分辨率做适配,因为 Android 没有提供原生 Gif 的 api 支持,所以这种方案还会遇到兼容性问题。另一种是用帧动画,但是帧动画占用空间比 Gif 还要大的多,也需要做适配。所以Lottie就粉墨登场了。

screens_1

Lottie做什么?

使用Lottie开发的流程是: 设计师在AE中设计完成你的动画,通过bodymoving插件导出纪录动画信息的JSON文件,然后开发人员使用 Lottie 的Android,iOS,React Native apps开源动画库读取这份JSON文件, 解析动画结构和参数信息并渲染。

image.png

相关工具:

  • Adobe AE CC 2017版本
  • ZXP installer AE插件安装工具,先安装这个。
  • bodymovin AE动画导出为JSON文件的插件。
    • 下载ZIP文件,解压得到bodymovin.zxp
    • 打开ZXP in staller, 将bodymovin.zxp拖进去安装。


      image.png

Lottie的优点

  1. 设计即所见: 设计师用AE设计好动画后直接导出Json文件,Lottie 解析Json文件后调Core Animation的API绘制渲染。还原度更好,开发成本更低。

  2. 跨平台: 支持iOS、Android、React Native。

  3. 性能:Lottie对于从AE导出的Json文件,用Core Animation做矢量动画, 性能较佳。Lottie 对解析后的数据模型有内存缓存。但是对多图片帧动画,性能比较差。

  4. 支持动画属性多:比起脸书的Keyframes,Lottie支持了更多AE动画属性,比如Mask, Trim Paths,Stroke (shape layer)等。

  5. 包大小,相比动辄上百K的帧动画,Json文件包大小很小。有图片资源的情况下,同一张图片也可以被多个图层复用,而且运行时内存中只有一个UIImage对象(iOS)。

庖丁解牛: Lottie iOS 的实现

Lottie动画库主要由两个部分组成:解析渲染

解析

复杂的AE动画用bodymoving导出后,其复杂的图层关系、动画属性都会映射到一串Json中。Lottie第一步要做的就是将data.json中的结构化数据解析成对应的模型类。
比如:AffterEffect新建项目时新建一个合成, Composition需要指定起始帧时间,终止时间 ,帧率:

导出成data.json后,对应的字段:

代码里LOTComposition模型类对应的属性:

@property (nonatomic, readonly) NSNumber *startFrame;   // 起始帧
@property (nonatomic, readonly) NSNumber *endFrame;     // 结束帧
@property (nonatomic, readonly) NSNumber *framerate;    // 帧率

下面是Lottie里简略的数据模型类关系图:

image.png

LOTComposition是整个数据模型,有点像个大画布。它有属性assetGroup(资源) 。如果AE动画有用到png图片,bodymovin导出的文件后,image文件夹下会有对应的png图片 。每张图的信息抽象在一个LOTAsset对象里,主要属性是本地路径(供加载用)、referenceID(跟对应图层做关联) 。LOTComposition对象还有一个属性是,layerGroup(图层组),是一个图层数组 。所有酷炫动画拆解后不过只是不同图层、不同属性在同一时刻的变化效果。 对应AE软件,图层数据模型纪录了一些属性帧动画信息,比如属性动画位移(position)、缩放(scale)、透明度(opacity)、旋转(rotation)信息。这些信息被解析后存储在一些属性类里,存初始时间、结束时间、帧率、插值用的某帧对应的值、时间函数等。用他们直接构造iOS 的Core Animation 动画对象。

比如这里有个动画,内圆点有透明度渐变动画(由0到1,再从1到0),导出后属性动画都在"ks"字典中,其中透明度又在“o”这个字典中。Lottie解析后Layer会存一个LOTAnimatableNumberValue对象,纪录动画信息。如下图:

7月-19-2017 15-14-46.gif

image.png

这些属性动画数据在Lottie里都用类似的对象存着,并提供了转化为CAKeyframeAnimation的接口。

image.png

如上类图,LOTLayer 还有叫shapes的数组,存了一堆LOTShapeGroup对象,这啥呢?其实是在AE中有个Shape的概念,是颜色、形状、透明度、等一些属性的组合.

还是上面那个动画为例子,内圆点形状和颜色在 ae属性和json文件表示:


image.png
image.png

渲染

解析好图层结构数据和动画参数, Lottie-iOS调用Core Animation建图层数和动画渲染。整个视图有一个叫_childContainerLayer的图层作为容器图层,也是图层树的根节点,开始根据数据往上添加子Layer. 比如上面例子的动画, 有1个合成,2个图层。构建图层树时,先根据LOTComposition模型数据创建LOTCompositionLayer对象,作为第一个子图层;然后LOTCompositionLayer 再根据LOTComposition中的layers数组创建对应的LOTLayerView图层2个。

image.png

其中LOTLayerView会负责,用之前解析出来的属性动画对象,构建动画组CAAnimationGroup。

  NSMutableDictionary *keypaths = [NSMutableDictionary dictionary];
  if (_layerModel.opacity) {
    [keypaths setValue:_layerModel.opacity forKey:@"opacity"];
  }
  if (_layerModel.position) {
    [keypaths setValue:_layerModel.position forKey:@"position"];
  }
  if (_layerModel.anchor) {
    [keypaths setValue:_layerModel.anchor forKey:@"anchorPoint"];
  }
  if (_layerModel.scale) {
    [keypaths setValue:_layerModel.scale forKey:@"transform"];
  }
  if (_layerModel.rotation) {
    [keypaths setValue:_layerModel.rotation forKey:@"sublayerTransform.rotation"];
  }
  if (_layerModel.positionX) {
    [keypaths setValue:_layerModel.positionX forKey:@"position.x"];
  }
  if (_layerModel.positionY) {
    [keypaths setValue:_layerModel.positionY forKey:@"position.y"];
  }
    
  _animation = [CAAnimationGroup LOT_animationGroupForAnimatablePropertiesWithKeyPaths:keypaths];
  
  if (_animation) {
    [_childContainerLayer addAnimation:_animation forKey:@"LottieAnimation"];
  }

这是渲染相关的类简图:它还支持mask跟裁剪等其他效果。


image.png

使用中的痛点:

  1. 支持AE动画属性有限,有的AE动画效果bodymoving无法导出,还有一些缺陷bodymoving导出的矢量动画无法支持。比如尚未看到支持阴影的效果
  2. 有些矢量动画 ,对设计师的要求比较高。而且蛮多设计师不会使用AE。

资源网站

https://www.lottiefiles.com/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容