iOS动画原理--模型树和呈现树

模型树和呈现树

CoreAnimation作为一个复合引擎,将不同的视图层组合在屏幕中,并且存储在图层树中,向我们展示了所有屏幕上的一切。
整个过程其实经历了三个树状结构,才显示到了屏幕上:模型树-->呈现树-->渲染树,如图:

通常,我们操作的是模型树,在重绘周期最后,我们会将模型树相关内容(层次结构、图层属性和动画)序列化,通过IPC传递给专门负责屏幕渲染的渲染进程。渲染进程拿到数据并反序列化出树状结构--呈现树。这个呈现图层实际上是模型图层的复制,但是它的属性值代表了在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值。

我们可以通过CALayer的-presentationLayer方法来访问对应的呈现树图层。注意呈现图层仅仅当图层首次被提交(就是首次第一次在屏幕上显示)的时候创建,所以在那之前调用-presentationLayer将会返回nil。你可能注意到有一个叫做–modelLayer的方法。在呈现图层上调用–modelLayer将会返回它正在呈现所依赖的CALayer。通常在一个图层上调用-modelLayer会返回–self(实际上我们已经创建的原始图层就是一种数据模型)。

一个移动的图层是如何通过数据模型呈现的

大多数情况下,你不需要直接访问呈现图层,你可以通过和模型图层的交互,来让Core Animation更新显示。两种情况下呈现图层会变得很有用,一个是同步动画,一个是处理用户交互。

当模型树上带有动画特征时,提交到渲染进程后,渲染进程会根据动画特征,不断修改呈现树上的图层属性,并同时不断的在屏幕上渲染出来,这样我们就看到了动画。

如果你想让你做动画的图层响应用户输入,你可以使用-hitTest:方法来判断指定图层是否被触摸,这时候对呈现图层而不是模型图层调用-hitTest:会显得更有意义,因为呈现图层代表了用户当前看到的图层位置,而不是当前动画结束之后的位置。

模型树与呈现树关系的比喻

在CALayer内部,它控制着两个属性:presentationLayer(以下称为P)和modelLayer(以下称为M)。P只负责显示,M只负责数据的存储和获取。我们对layer的各种属性赋值比如frame,实际上是直接对M的属性赋值,而P将在每一次屏幕刷新的时候回到M的状态。比如此时M的状态是1,P的状态也是1,然后我们把M的状态改为2,那么此时P还没有过去,也就是我们看到的状态P还是1,在下一次屏幕刷新的时候P才变为2。而我们几乎感知不到两次屏幕刷新之间的间隙,所以感觉就是我们一对M赋值,P就过去了。P就像是瞎子,M就像是瘸子,瞎子背着瘸子,瞎子每走一步(也就是每次屏幕刷新的时候)都要去问瘸子应该怎样走(这里的走路就是绘制内容到屏幕上),瘸子没法走,只能指挥瞎子背着自己走。可以简单的理解为:一般情况下,任意时刻P都会回到M的状态。而当一个CAAnimation(以下称为A)加到了layer上面后,A就把M从P身上挤下去了。现在P背着的是A,P同样在每次屏幕刷新的时候去问他背着的那个家伙,A就指挥它从fromValue到toValue来改变值。而动画结束后,A会自动被移除,这时P没有了指挥,就只能大喊“M你在哪”,M说我还在原地没动呢,于是P就顺声回到M的位置了。这就是为什么动画结束后我们看到这个视图又回到了原来的位置,是因为我们看到在移动的是P,而指挥它移动的是A,M永远停在原来的位置没有动,动画结束后A被移除,P就回到了M的怀里。
动画结束后,P会回到M的状态(当然这是有前提的,因为动画已经被移除了,我们可以设置fillMode来继续影响P),但是这通常都不是我们动画想要的效果。我们通常想要的是,动画结束后,视图就停在结束的地方,并且此时我去访问该视图的属性(也就是M的属性),也应该就是当前看到的那个样子。按照官方文档的描述,我们的CAAnimation动画都可以通过设置modelLayer到动画结束的状态来实现P和M的同步。

动画实现方式

动画,顾名思义就是动起来的画面,任何使屏幕上的视图随时间不断变化的技术都可以实现动画。在iOS中,实现动画的方式主要分两大类:CoreAnimation动画和非CoreAnimation动画。

CoreAnimation动画

CoreAnimation动画,即基于事务的动画,是最常见的动画实现方式。动画执行者是专门负责渲染的渲染进程,操作的是呈现树。我们应该尽量使用CoreAnimation来控制动画,因为CoreAnimation是充分优化过的:

  1. 更高效的绘制

基于Layer的绘图过程中,CoreAnimation通过硬件操作位图(变换、组合等),产生动画的速度比软件操作的方式快很多。

基于View的绘图过程中,view被改动时会触发的drawRect:方法来重新绘制位图,但是这种方式需要CPU在主线程执行,比较耗时。而CoreAnimation则尽可能的操作硬件中已缓存的位图,来实现相同的效果,从而减少了资源损耗。

How Core Animation draws content
  1. 更高效的动画

在动画过程中,CoreAnimation会通过硬件来一帧一帧的绘制。你所做的就是指定动画的起点和终点,其他的都让CoreAnimation来做。当然你也可以自定义动画参数,否则CoreAnimation会使用合适的默认值。

非CoreAnimation动画

非CoreAnimation动画执行者是当前进程,操作的是模型树。常见的有定时器动画和手势动画。定时器动画是在定时周期触发时修改模型树的图层属性;手势动画是手势事件(比如UIScrollView的didScrollView)触发时修改模型树的图层属性。两者都能达到视图随着时间不断变化的效果,即实现了动画。

非CoreAnimation动画动画过程中实际上不断改动的是模型树,而呈现树仅仅成了模型树的复制品,状态与模型树保持一致。整个过程中,主要是CPU在主线程不断调整图层属性、布局计算、提交数据,没有充分利用到CoreAnimation强大的动画控制功能。

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

推荐阅读更多精彩内容

  • 书写的很好,翻译的也棒!感谢译者,感谢感谢! iOS-Core-Animation-Advanced-Techni...
    钱嘘嘘阅读 2,278评论 0 6
  • 在前面的学习中,我们讨论了CoreAnimation除了动画外可以做到的任何事情。但是动画是CoreAni...
    小猫仔阅读 1,508评论 0 0
  • 前言 本文只要描述了iOS中的Core Animation(核心动画:隐式动画、显示动画)、贝塞尔曲线、UIVie...
    GitHubPorter阅读 3,583评论 7 11
  • CoreAnimation:Core Animation自身并不是一个绘图系统。它只是一个负责在硬件上合成和操纵应...
    YGoooooooooal阅读 558评论 0 1
  • 前言 代码每个人都会写。但是,能把代码写的优美,把结构设计的足够灵活,并且让人赞叹的人却很少。尤其在中国这样的大环...
    欧阳锋阅读 8,895评论 7 15