前言


配置属性动画或者关键帧动画的方式是多种多样的。需要同时执行多个动画或者顺序执行多个动画的APP,可以通过高级的方式同步这些动画的timing或者将这些动画绑定在一起。我们也可以使用其他类型的动画对象来创建可视化的transitions和别的有趣的动画效果。

 

过渡动画支持Layer可见性的变化


就像本级标题名字所说一样,一个transition动画对象为Layer创建一个动画性的过渡效果。transistion对象最常用的方法就是以协调的方式让一个Layer动画形式的出现,并让另外一个Layer动画形式的消失。和属性动画不一样,属性动画是改变Layer的一个属性;而transition动画操作layer缓存的image用来创建可视化效应,通过只调整属性这些可视化效应是很难或者几乎不肯能完成的。标准的transition类型可以用来实现渐显、push、移除或者交叉渐隐动画。在OSX上,我们也可以使用Core image filter创建具有特殊效应的transitions,例如擦拭、卷页、波纹或者自定义的其他效果。

为了执行transition动画,我们可以创建CATransition对象并将其添加到相关的Layers。我们在使用transition对象的时候可以指定transition的类型、开始和结束进度点。开始动画前,可以设置开始和结束进度值,这两个值可以让我们的transition动画看起来像从开始值开始,和结束值结束。

代码5-1展示了如何在两个View之间创建push 过渡动画。在这个例子中,myView1和myView2是在同一个父视图上相同的position,并且myView1是可见的在最初。动画效果为myView1想做滑出知道完全隐藏,同时myView2从右边滑入知道完全显示。为了确保在动画的结束时候两个view相应的可见性是正确的,我们需要更新两个view的hidden属性。

 

代码5-1在iOS中两个view之间过度动画


CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0; // Add the transition animation to both layers
[myView1.layer addAnimation:transition forKey:@"transition"];
[myView2.layer addAnimation:transition forKey:@"transition"]; // Finally, change the visibility of the layers.
myView1.hidden = YES;
myView2.hidden = NO;

 

当两个layer都需要相同的过度动画时候,我们可以让他们使用相同的transition对象。使用相同的transition对象也能简化代码。

 

自定义动画时间函数


时间控制函数是动画的重要部分。通过核心动画中CAMediaTiming协议的方法和属性,我们可以为动画指定精确的时间信息。CAAnimation类遵守该协议,因此我们能够指定动画对象的时间信息,隐式动画对象默认封装了这些信息,并优先使用默认的信息。

对于如何理解时间信息和动画时,理解Layer对象和time之间关系是很重要的。每个Layer有他们自己的局部时间,Layer使用自己的局部时间来管理动画时间。通常情况下,两个不同Layer的局部时间是非常接近的,以至于在为这两个Layer指定相同的时间值时,用户也察觉不到。然而,Layer的局部时间能够被它的父Layer和它自身的时间参数所修改。例如,改变Layer的[speed]属性能够引起Layer(和他的sublayer)的动画的duration发生成比例的变化。

为了帮助我们确保时间值是恰当的,CALayer类定义了convertTime:fromLayer: and convertTime:toLayer:方法。我们可以使用这些方法将一个修正的时间值转换为layer的局部时间,或者将一个layer的时间值转换到另外一个Layer。这两个方法涉及到时间相关的属性并返回一个值,我们将这个值可以用于别的layer,这两个方法所涉及到的时间属性也会影响layer的局部时间。代码5-3展示了定期用于获得一个layer的当前局部时间。通过CACurrentMediaTime函数可以获取计算机当前时间,同时可将这个时间用于转换出Layer的局部时间。

 

代码5-3过的Layer的本地时间


CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];

 

一旦我们有了相对于layer局部时间的值,我们可以使用该值去更新动画对象或Layer的时间相关的属性。通过设置这些时间属性,我们可以获得许多有趣的动画行为,这些属性包含以下几种:

  • 使用beginTime属性设置动画的开始时间。通常,动画在下个更新循环开始执行。我们可以使用beginTime参数去延迟几秒动画的开始。将两个动画顺序的关联在一起的方法就是,将一个动画的beginTime和另外一个动画的结束值设置为相同的值。

    如果我们延迟动画的开始时间,我们也应该设置fillModel属性的值为kCAFillModeBackwards。这个模式将会使Layer显式动画的开始值,及时图层树上的Layer对象具有不同的值。如果不设置这个模式,我们将会看到一个到最终值跳跃性的显式在动画开始执行前。其他的模式也是可用的。

  • autoreverses属性将会引发动画以被指定的duration返回动画的开始值。我们将这个属性与repeatCount属性结合起来可以实现在开始值和结束值之间来回做动画。如果autoreversing为YES并为repeatCount属性设置整数值(例如1.0),那么将会引起动画停止在开始值;添加额外的一半动画(例如设置为1.5)将会使得动画停止在结束值的位置。

  • 在组动画中使用timeOffset属性能够让一些动画在组内某些动画之后开始。

 

暂停和重启动画


为了暂停动画,我们可以利用Layer遵守的CAMediaTiming协议,并设置Layer动画的speed为0.0。将speed设置为0将引起动画暂停,直到我们改变这个值为非0值动画才会结束暂停。代码5-4展示了简单的示例关于如何暂停和在暂停后重启动画。

 

5-4暂停和重启Layer的动画


-(void)pauseLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
} -(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}

 

显式动画帮助我们改变动画的参数


为Layer做的每一个改变必须是transaction的一部分。[CATransaction]类管理动画的创建、将动画组合在一起并将组合的动画以恰当的时间执行。大部分情况下,我们不需要创建自己的transactions。无论何时你为Layer添加显式和隐式动画,核心动画自动创建隐式transaction。然而,我们也能创建显式transactions去更准确的管理这些动画。

使用CATransaction类的方法,我们可以创建和管理transactions。调用begin类方法开始(隐式的创建)新的transaction;调用commit类方法结束transaction。在这两个方法之间调用我们想要作为transaction其中的变化。例如我们使用代码5-5变化layer的两个属性。

 

5-5创建显式的transaction


[CATransaction begin];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];

 

使用transactions最主要的原因就是在transaction的beginTime和commit中间,我们可以改变duration,timing函数和其他参数。我们能够也能够为transaction关联一个完成后执行的block,方便我们的APP能够在这组动画结束后的到通知。改变动画的参数,需要通过修改在使用setValue:forKey:方法修改transaction字典里面对应的key。例如,改变默认duration为10秒,我们应该改变kCATransactionAnimationDuration key,例如代码5-6展示

 

5-6改变动画的默认duration


[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
forKey:kCATransactionAnimationDuration];
// Perform the animations
[CATransaction commit];

 

当我们想要为不同的动画集合提供不同的值时,我们可以嵌套transactions。如果想要嵌套,只需要在begin类方法之后再次调用begin方法。每一个begin调用必须和-个commit方法对应。仅当我们提交最后一个最外层的commit方法时,核心动画才会开始相关的动画。

代码5-7展示了两个transaction的嵌套。在这个例子中这个内层的和外层的transaction改变相同的动画参数,但是使用不同的值。

 

5-7嵌套显式的transaction


[CATransaction begin]; // Outer transaction // Change the animation duration to two seconds
[CATransaction setValue:[NSNumber numberWithFloat:2.0f]
forKey:kCATransactionAnimationDuration];
// Move the layer to a new position
theLayer.position = CGPointMake(0.0,0.0); [CATransaction begin]; // Inner transaction
// Change the animation duration to five seconds
[CATransaction setValue:[NSNumber numberWithFloat:5.0f]
forKey:kCATransactionAnimationDuration]; // Change the zPosition and opacity
theLayer.zPosition=200.0;
theLayer.opacity=0.0; [CATransaction commit]; // Inner transaction [CATransaction commit]; // Outer transaction

 

为动画添加观看者视角


APP可以在三个维度控制Layer;简单的核心动画所展示的Layers是使用了平面投射,本质就是核心动画将3维空间投射到2维平面上了。默认情况下,具有相同尺寸和不同zPosition的Layers看起来像是一样大的,即使他们在Z轴上的坐标是不同的,也就是说我们不能想正常的人眼视角观看这些三维场景。然而,我们可以通过修改Layers的transformation矩阵,加入人眼观看视角。

当调整一个三维场景的视角时,我们需要调整superlayer的sublayerTransform矩阵(superlayer包含这些可被看到的layers),通过调整superlayer能够简化代码的工作量(如果不通过调整superlayer那么我们就需要把相同的视角相关信息应用到所有的子Layer),同时他也确保了视角是正确应用到同级的sublayers上(同级的sublayers可能在不同的平面重叠交叉)。

代码5-8展示了为父Layer创建简单的视角transform。在这种情况下,自定义的人眼视角的变化将会改变沿着Z轴到Layer的距离。通常为了保证Layers以期望的方式,我们为人眼视角指定一个正数值。数值越大看到的越远,数值越小看到的会越细致。

 

代码5-8为父Layer添加视角transform


CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/eyePosition; // Apply the transform to a parent layer.

 

在类似之上配置了父Layer情况下,我们可以改变任何子Layer的zPosition属性,并观察它们的尺寸(在基于它们到人眼位置)是如何变化的。

Core Animation 文档翻译 (第六篇)的更多相关文章

  1. Core Animation 文档翻译 (第一篇)

    Core Animation 文档翻译(第一篇)   2018-01-13  星期6 前言:作为iOS 开发,官方文档的阅读是很有必要的,值此周末便写下此文.作为iOS 实际经验3年的开发,之前的应用 ...

  2. Core Animation文档翻译 (第一篇)

    Core Animation 文档翻译(第一篇) 前言 作为iOS 开发,官方文档的阅读是很有必要的,值此周末便写下此文.作为iOS 实际经验3年的开发,之前有阅读并实践过经典的<iOS核心动画 ...

  3. Core Animation 文档翻译 (第二篇)

    Core Animation 文档翻译 (第二篇) 核心动画基础要素 核心动画为我们APP内Views动画和其他可视化元素动画提供了综合性的实现体系.核心动画不是我们APP内Views的替代品,相反, ...

  4. Core Animation 文档翻译(第三篇)

    Core Animation 文档翻译(第三篇) 设置Layer对象 当我们使用核心动画时,Layer对象是一切的核心.Layers 管理我们APP的可视化content,Layer也提供了conte ...

  5. Core Animation 文档翻译 (第四篇)

    Core Animation 文档翻译(第四篇) 让Layer的content动画起来 核心动画的基础接口以及为拥有Layer的View做的动画扩展接口,使得为Layer制作复杂动画变得简单化.例如改 ...

  6. Core Animation 文档翻译 (第八篇)—提高动画的性能

    前言 核心动画是提高基于APP动画帧率的好方式,但是核心动画的使用不代表性能的提升的保证.尤其在OSX,当使用核心动画时,我们仍需选择最有效的方式.和所有的性能相关的问题一样,我们应该使用工具时时的评 ...

  7. Core Animation 文档翻译 (第五篇)

      构建Layer层次结构 在APP中大多数情况下,将Layer和View对象结合使用是Layer最好的使用方式.然而,很多时候我们可能需要通过添加单独的Layer对象,以便增加视图继承层次:当为了提 ...

  8. Core Animation 文档翻译 (第七篇)——改变Layer的默认动画

    前言 核心动画使用action对象实现它的可视化动画.一个action对象是指遵循CAAction协议并定义了Layer相关的动画行为的对象.所有的CAAnimation对象实现了这个协议,无论何时L ...

  9. Core Animation 文档翻译—附录B(可动画的属性)

    前言   许多CALayer和CIFliter的属性都是可动画的.本节附录列出了这些属性默认使用的动画.   CALayer可动画属性   表B-1展示了CALayer类的可动画属性.针对每个属性此表 ...

随机推荐

  1. hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

    题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...

  2. cain使用方法

    首先安装cain,这里就不废话了 1, 选择中核弹标志左边的按一下,然后在sniffer右键点击第一个扫描内网所有ip 扫描完后选择网关的IP下面选择arp标志,在按一下上方空格处,+号变得可以使用了 ...

  3. 二叉排序树BST+求树深度算法

    #include "stdio.h" #include "malloc.h" typedef struct node { int key; struct nod ...

  4. python内建函数isinstance基础用法

      语法:isinstance(object,type) 作用:来判断一个对象是否是一个已知的类型.  其第一个参数(object)为对象,第二个参数(type)为类型名(int...)或类型名的一个 ...

  5. React Native学习(四)—— 写一个公用组件(头部)

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  6. TCP层的分段和IP层的分片之间的关系 & MTU和MSS之间的关系 (转载)

    首先说明:数据报的分段和分片确实发生,分段发生在传输层,分片发生在网络层.但是对于分段来说,这是经常发生在UDP传输层协议上的情况,对于传输层使用TCP协议的通道来说,这种事情很少发生. 1,MTU( ...

  7. HDU 2243 Knight Moves

    题目: A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find th ...

  8. iframe及与页面之间的通信

    获取iframe对象 iframe元素本身是位于父级页面中的,所以你可以像一个普通元素一样的使用和操作它 代表了iframe内容window对象是作为一个页面的属性加入到iframe中的, 为了让父级 ...

  9. 解决DEDECMS Call to undefined function dede_htmlspecialchars()

    作者:DEDECMS建站网 关注: 3610 时间:2015-11-18 16:39 内容详情 以下内容您可能感兴趣: 织梦官方在2015年6月18日更新了织梦5.7,为了兼容php5.4+,修改了/ ...

  10. vue 开发2017年变化回顾及2018年展望

    vue.js 变化 从 github 的发布记录我们可以看到2017年 vue.js 的第一个发布为 v2.1.9,最后一个为 v2.5.13,主要发布小版本 2.2~2.5.这些发布提升了vue 与 ...