实现动画方式深度解析(六) —— Core Animation Basics(三)

版本记录

版本号 时间
V1.0 2017.09.21

前言

app中好的炫的动画可以让用户耳目一新,为产品增色不少,关于动画的实现我们可以用基本动画、关键帧动画、序列帧动画以及基于CoreGraphic的动画等等,接下来这几篇我就介绍下我可以想到的几种动画绘制方法。具体Demo示例已开源到Github —— 刀客传奇,感兴趣的可以看我写的另外几篇。
1. 实现动画方式深度解析(一) —— 播放GIF动画(一)
2. 实现动画方式深度解析(二) —— 播放GIF动画之框架FLAnimatedImage的使用(二)
3. 实现动画方式深度解析(三) —— 播放序列帧动画(一)
4. 实现动画方式深度解析(四) —— QuartzCore框架(一)
5. 实现动画方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)

Core Animation Basics

核心动画提供了一个通用的系统,用于动画化您的app视图和其他视觉元素。 核心动画不是您的app视图的替代品。 相反,它是一种视图集成的技术,可以为动画内容提供更好的性能和支持。 通过将视图的内容缓存到可以由图形硬件直接操纵的位图中来实现此行为。 在某些情况下,这种缓存行为可能需要您重新思考如何呈现和管理应用程序的内容,但大多数时候您使用Core Animation而无需知道它。 除了缓存视图内容之外,Core Animation还定义了一种指定任意可视内容的方法,将该内容与视图集成,并将其与其他所有内容一起动画化。

您可以使用Core Animation来动画更改应用程序的视图和视觉对象。 大多数更改涉及修改视觉对象的属性。 例如,您可以使用Core Animation来动态更改视图的位置,大小或不透明度。 当您进行这样的更改时,核心动画将在当前的属性值和您指定的新值之间动画化。 通常不会使用Core Animation来代替视图的内容,每秒60次,如漫画。 相反,您可以使用Core Animation将视图的内容移动到屏幕上,将内容淡入或淡出,对视图应用任意图形转换,或更改视图的其他视觉属性。


Layers Provide the Basis for Drawing and Animations

layer对象是组织在3D空间中的2D表面,并且是您使用Core Animation执行的所有操作的核心。 像视图一样,layer管理有关其表面的几何,内容和视觉属性的信息。 不同于视图,layer没有定义自己的外观。 layer层仅管理位图周围的状态信息。 位图本身可以是您自己指定的视图或您指定的固定图像的结果。 因此,您在应用程序中使用的main layer被认为是模型对象,因为它们主要管理数据。 这个概念很重要,因为它影响动画的行为。

1. The Layer-Based Drawing Model - 基于Layer的绘画模型

大多数图层在您的应用程序中没有实际绘制。 相反,一个图层捕获您的应用程序提供的内容,并将其缓存在位图中,该位图有时称为后备存储。 当您随后更改图层的属性时,您所做的就是更改与图层对象关联的状态信息。 当更改触发动画时,Core Animation会将图层的位图和状态信息传递给图形硬件,从而使用新信息渲染位图的工作,如图1-1所示。 在硬件中操作位图产生比软件更快的动画。

因为它操纵一个静态位图,基于层的绘图与更传统的基于视图的绘图技术显着不同。 使用基于视图的绘图,对视图本身的更改通常会导致调用视图的drawRect:方法以使用新参数重绘内容。 但是以这种方式绘制是昂贵的,因为它是使用主线程上的CPU完成的。 Core Animation可以通过在硬件中操作缓存的位图来实现相同或相似的效果,从而避免这种消耗。

虽然Core Animation尽可能使用缓存的内容,但您的应用仍然必须提供初始内容并时时更新。 您的应用程序有几种方式为图层对象提供内容,这些内容在提供图层的内容中有详细描述 Providing a Layer’s Contents. 。

2. Layer-Based Animations - 基于layer的动画

层对象的数据和状态信息与屏幕上该层内容的视觉呈现分离。 这种去耦使得核心动画成为一种插入自己的方式,并将变化从旧的状态值转换为新的状态值。 例如,更改图层的position属性会导致Core Animation将图层从当前位置移动到新指定的位置。 与其他属性类似的更改会导致适当的动画。 下图显示了您可以在图层上执行的一些动画类型。 有关触发动画的图层属性列表,请参阅动画属性 Animatable Properties

在动画过程中,Core Animation可以在硬件中为您提供所有的逐帧绘图。 所有你需要做的是指定动画的开始和结束点,并让核心动画做其余的。 您还可以根据需要指定自定义定时信息和动画参数; 但是,如果没有,Core Animation提供了合适的默认值。

有关如何启动动画和配置动画参数的更多信息,请参阅动画图层内容 Animating Layer Content


Layer Objects Define Their Own Geometry - 定义自己几何的层对象

layer的任务之一是管理其内容的视觉几何。 视觉几何包含关于该内容的界限,其在屏幕上的位置以及该layer是以任何方式旋转,缩放或变换的信息。 像视图一样,图层layer具有框架和边框,您可以使用它们来定位图层及其内容。 图层还具有视图没有的其他属性,例如锚点,其定义了操作发生的位置。 指定层几何的某些方面的方式也不同于如何为视图指定信息。

1. Layers Use Two Types of Coordinate Systems - 使用两种不同坐标系统的图层

图层利用基于点的坐标系和单位坐标系来指定内容的位置。 使用哪个坐标系取决于正在传达的信息的类型。 当指定直接映射到屏幕坐标的值时或者必须相对于另一层指定值时,使用基于点的坐标,例如对于图层的position属性。 当值不应与屏幕坐标相关时使用单位坐标,因为它相对于某个其他值。 例如,图层的anchorPoint属性指定了相对于图层本身的边界的点,这可以改变。

基于点的坐标最常见的用法是指定图层的大小和位置,使用层的边界和位置属性。 边界定义了图层本身的坐标系,并包含图层在屏幕上的大小。 position属性定义了图层相对于其父坐标系的位置。 尽管图层具有frame属性,但该属性实际上是从边界和位置属性中的值导出的,并且使用的频率较低。

层的边界和框架矩形的方向总是与底层平台的默认方向相匹配。 下图显示了iOS和OS上边界矩形的默认方向。

上图中要注意的一点是位置属性位于图层的中间。 该属性是根据图层的anchorPoint属性中的值定义更改的几个属性之一。 锚点表示某些坐标来源的点,并在“锚点影响几何操作 Anchor Points Affect Geometric Manipulations”中有更详细的描述。

锚点是您使用单位坐标系指定的几个属性之一。 核心动画使用单位坐标来表示当图层的大小变化时其值可能会改变的属性。 您可以将单位坐标视为指定总可能值的百分比。 单位坐标空间中的每个坐标的范围都为0.0到1.0。 例如,沿x轴,左边缘在坐标0.0处,右边缘处于坐标1.0。 沿y轴,单位坐标值的方向取决于平台,如下图所示。

注意:直到OS X 10.8,geometryFlipped属性才能在需要时更改图层y轴的默认方向。 有时需要使用这个属性来纠正一个层的方向。 例如,如果父视图使用翻转变换,则其子视图(及其相应图层)的内容通常会反转。 在这种情况下,将子层的geometryFlipped属性设置为YES可以解决问题。 在OS X 10.8及更高版本中,AppKit为您管理此属性,您不应该修改它。 对于iOS应用程序,建议您不要使用geometryFlipped属性。

所有坐标值,无论它们是点还是单位坐标都被指定为浮点数。 使用浮点数允许您指定可能落在正常坐标值之间的精确位置。 使用浮点值是很方便的,特别是在打印期间或当绘制到Retina显示屏上时,其中一个点可能由多个像素表示。 浮点值允许您忽略底层设备分辨率,并仅以所需精度指定值。

2. Anchor Points Affect Geometric Manipulations - 锚点影响几何操纵

与图层的锚点相关的几何相关操作发生,您可以使用图层的anchorPoint属性进行访问。 当处理层的位置或变换属性时,锚点的影响是最显着的。 position属性总是相对于图层的锚点指定的,并且您应用于图层的任何转换也会相对于锚点发生。

下图演示了如何将锚点从其默认值更改为不同的值会影响图层的位置属性。 即使图层没有在父层的边界内移动,将锚点从图层的中心移动到图层的边界起点也会改变position属性的值。

下图显示了如何改变锚点影响应用于图层的变换。 当您将旋转变换应用于图层时,旋转将发生在锚点周围。 因为默认情况下,锚点被设置在层的中间,所以通常会产生你期望的那种旋转行为。 但是,如果更改锚点,旋转结果将不同。

3. Layers Can Be Manipulated in Three Dimensions - 图层可以在三维方向操作

每个层都有两个变换矩阵,您可以使用它们来操纵图层及其内容。 CALayertransform属性指定要应用于图层及其嵌入的子图层的转换。 通常,当您要修改图层本身时,您可以使用此属性。 例如,您可以使用该属性缩放或旋转图层或暂时更改其位置。 sublayerTransform属性定义了仅适用于子层的附加转换,最常用于向场景内容添加透视视觉效果。

通过将坐标值乘以数字矩阵来转换操作,以获得代表原始点的转换版本的新坐标。 因为Core Animation值可以在三维中指定,所以每个坐标点都有四个必须乘以4×4矩阵的值,如下图所示。 在Core Animation中,图中的变换由CATransform3D类型表示。 幸运的是,您不必直接修改此结构的字段来执行标准转换。 核心动画提供了一套全面的函数用于创建缩放,转换和旋转矩阵以及进行矩阵比较。 除了使用函数操纵变换之外,Core Animation还扩展了键值编码KVC支持,以允许您使用关键路径修改变换。 有关可以修改的关键路径的列表,请参阅CATransform3D密钥路径 CATransform3D Key Paths

下图显示了您可以进行的一些更常见的转换的矩阵配置。 通过identity变换乘以任何坐标返回完全相同的坐标。 对于其他变换,如何修改坐标完全取决于您更改的矩阵组件。 例如,要仅沿x轴转换,您将为转换矩阵的tx组件提供非零值,并将ty和tz值保留为0,对于旋转,您将提供目标旋转角度适当的正弦和余弦值。

Matrix configurations for common transformations

有关用于创建和操作变换的功能的信息,请参阅Core Animation Function Reference


Layer Trees Reflect Different Aspects of the Animation State - layer树反映动画状态的不同方面

使用Core Animation的app有三组图层layer对象,每套图层对象在使您的app的内容出现在屏幕上方面具有不同的作用:

  • 模型层树(或简称“层树”)中的对象是您的应用程序与之最相互影响的对象。 此树中的对象是存储任何动画的目标值的模型对象。 无论何时更改图层的属性,都可以使用其中一个对象。

  • 展示树中的对象包含任何正在运行的动画的飞行中值。 而层树对象包含动画的目标值,而呈现树中的对象会反映当前值在屏幕上显示的值。 您不应该修改此树中的对象。 而是使用这些对象来读取当前的动画值,也许是从这些值开始创建一个新的动画。

  • 渲染树中的对象执行实际动画,并且对Core Animation是私有的。

每组图层layer对象被组织成层次结构,如app中的视图。 实际上,对于一个能够为其所有视图启用图层的app,每个树的初始结构恰好匹配了视图层次结构。 但是,app可以根据需要向层次结构中添加额外的图层layer对象(即与视图无关的图层)。 您可以在不需要视图所有开销的内容的情况下优化app的性能。 下图显示了在一个简单的iOS app中找到的图层layer细分。 示例中的窗口包含一个内容视图,该视图本身包含一个按钮视图和两个独立的图层对象。 每个视图都有一个相应的图层对象,它形成图层层次结构的一部分。

对于图层layer树中的每个对象,展示树和渲染树中都有一个匹配的对象,如下图所示。 如前所述,app主要使用图层layer树中的对象,但有时可以访问展示树中的对象。 具体来说,访问layer树中的对象的 presentationLayer属性会返回呈现树中的相应对象。 您可能希望访问该对象以读取动画中间的属性的当前值。

The layer trees for a window

重要:只有当动画在飞行中时,才能访问展示树中的对象。 当动画正在进行时,展示树包含当时在屏幕上显示的图层值。 此行为与图层layer树不同,图层树总是反映您代码设置的最后一个值,相当于动画的最终状态。


The Relationship Between Layers and Views - 图层和视图的关系

图层不能替代您的app的视图,也就是说,您无法仅基于图层layer对象创建可视界面。 layer层为您的view提供基础部分。 具体来说,图层使绘图和动画视图的内容变得更加容易和有效,并且在执行此操作时保持较高的帧速率。 但是,还是有很多事情层layer是不能做的。 层layer不能处理事件、绘制内容、参与响应者链或做许多其他事情。 因此,每个app仍然必须有一个或多个视图来处理这些交互。

在iOS中,每个视图都由相应的图层对象支持,但在OS X中,您必须确定哪些视图应具有图层。 在OS X v10.8及更高版本中,将图层添加到所有视图可能是有意义的。 但是,您不需要这样做,并且在开销不合理和不必要的情况下仍可禁用层。 图层确实会增加应用程序的内存开销,但是它们的优势往往超过劣势,因此在禁用层支持之前,最好测试应用程序的性能。

为视图启用图层支持时,可以创建所谓的支持层的视图。 在层次支持的视图中,系统负责创建底层图层对象,并保持该图层与视图同步。 所有iOS视图都是层次支持的,OS X中的大多数视图也是如此。 但是,在OS X中,您还可以创建一个图层托管视图,这是您自己提供图层对象的视图。 对于层次托管视图,AppKit采用手动管理层,不会修改它以响应视图更改。

注意:对于层次支持的视图,建议您尽可能操纵视图,而不是图层。 在iOS中,视图只是围绕层对象的薄包装,因此您对图层进行的任何操作通常都可以正常工作。 但是在iOS和OS X中都有这样的情况,其中操纵图层而不是视图可能不会产生所需的结果。 尽可能地,本文件指出了这些陷阱,并尝试提供方法来帮助您解决这些问题。

除了与视图相关联的图层之外,还可以创建没有相应视图的图层对象。 您可以将这些独立图层对象嵌入到应用程序中的任何其他图层对象中,包括与视图关联的图层对象。 通常使用独立图层对象作为特定优化路径的一部分。 例如,如果要在多个地方使用相同的图像,则可以加载图像一次,并将其与多个独立图层对象相关联,并将这些对象添加到图层树中。 每个层然后引用源图像,而不是尝试在内存中创建该图像的自己的副本。

有关如何为应用程序的视图启用图层支持的信息,请参阅Enabling Core Animation Support in Your App。 有关如何创建层对象层次结构的信息,以及有关何时可以这样做的提示,请参阅Building a Layer Hierarchy

后记

未完,待续~~~

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

推荐阅读更多精彩内容