Core Animation——高级动画技巧

本文主要是苹果官方文档core animation programming guide中Advanced Animation Tricks的总结,原文地址

过渡动画(transition animations)支持改变layer的可视性(visibility)

一个过渡动画对象(transition animation object)为layer创建了一个动画的视觉过渡。transition object最常用的用法就是以一种协调一致的方式动画的显示一个layer,同时消失另一个layer。和基于属性的动画(property-based animation)不同,基于属性的动画是动画中改变layer的属性,transition 动画是操纵控制layer的 cached image 达到创建可视的动画效果,通过单一的改变属性是不可能达到这种效果的。transition的标准类型可以让我们进行reveal,push,move 和 crossfade 动画。
为了进行transition 动画,我们需要创建CATransition对象,并将其添加到layer上,就这么简单。
下面代码例子:
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;
在上面的代码例子中,myView1和myView2有同样的parent view,并且它们的位置和大小都相同,但是只有myView1是可见的。push过渡动画是是myView1在左边划出直到消失,同时myView2会从右边划进来,并变为可见的。
当两个layer有相同的过渡,可以对它们使用相同的transition object。当然,如果layer的过渡参数不同,则要为每一个layer要创建对应的transition object。

自定义动画的时间

timing是动画中重要的一部分,core animation通过协议CAMediaTiming中定义的方法和属性获取进行动画时所需要的时间信息。在core animation中,有两个类实现了此协议,CAAnimation和CALayer,CAAnimation就不用多说了,其实现CAMediaTiming协议提供动画对象所需要的时间信息。CALayer实现此协议,主要是为隐式的动画提供一些时间相关的信息,尽管隐式的transaction object已经提供了一些缺省的时间信息。
每一个layer都有自己的local time,用于管理动画时间。正常情况下两个不同的layer的local time十分接近,我们只需对它们指定相同的时间值,用户不会注意到什么的。但是一个layer的local time可能被她的parent layer 或者它自己的timing属性改变。例如,改变一个layer的speed属性会导致layer的动画持续时间也改变。
CALayer定义了两个方法convertTime:fromLayer: 和 converTime:toLayer: ,使用这两个方法可以转换一个固定的时间值相对于layer的local time(you can use these methods to convert a fixed time value to the local time of a layer  or  to convert time values from one layer to another)。下面的代码展示了获取layer的当前 local time。其中CACurrentMediaTime函数会返回当前cpu的时钟时间。
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];

暂停和恢复动画

可以暂停动画,这要感谢采用了CAMediaTiming协议,当需要暂停layer的动画的时候,设置speed为0,当恢复动画的时候将其设置为非零值,如下简单代码:
-(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;
}

tip:关于CAMediaTiming协议中有很多属性,文档中解释的不是很清楚,我准备在下一篇博文中好好总结一下。

使用显式事务(explicit transaction)去改变动画参数

layer的每一个变化都属于transaction的一部分,CATransaction类管理animation的创建、分组和执行(在恰当的时间)。在大多数情况下,我们并不需要去创建自己的transaction。当我们给layer添加一个显式或者隐式的动画的时候,core animation会自动的为我们创建一个隐式的transaction。当然,我们也可以创建一个显式的transaction去管理animations。
我们使用CATransaction类的方法去创建和管理transaction,当要启动(创建是隐式的)一个新的transaction的时候调用类方法begin,结束一个transaction时,调用commit。下面是一个小的例子:
[CATransaction begin];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];

使用显式transaction的主要原因是我们可以改变其参数,包括duration,timing function等等 ,也可以为一个transaction赋值一个completion block,因此,当动画都结束之后,会执行此block。
下面的代码修改默认的动画时间(duration)
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
                 forKey:kCATransactionAnimationDuration];
// Perform the animations
[CATransaction commit];

当我们想要为transaction中不同动画设置不同的参数,可以嵌套transaction,但是要注意每一个begin都要对应一个commit,下面是一个例子:
[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

为动画添加perspective

layer是支持三维空间的,但是为了简单,core animation通常使用平行投影(parallel projection) 显示一个layer,这会讲一个layer的显式扁平化到一个二维空间上。缺省情况下,当两个size相同的layer,具体不同的zPosition值,但是显示的时候size还是相同,不论zPosition相差多大。但是我们可以通过改变layer的transformation matrix矩阵使其包含远景信息(perspective information).
当我们改变perspective信息的时候,通常改进super layer的sublayerTransform属性,这样就行应用到所有的sublayer上。
下面就是在parent layer上添加一个perspective transform的方法:
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/eyePosition;
 
// Apply the transform to a parent layer.
myParentLayer.sublayerTransform = perspective;

通过eyePosition为一个正值,大多数情况下取值500~2000,当此值越大时,显示越扁平化,3d效果越不明显。相反,值越小的时候,越能产生强烈的效果。
现在,当两个有相同size的child layer,不同的zPosition值,可以看到在屏幕上会呈现不同的大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值