Allen Chiang

iOS程序猿的blog

© 2014. All rights reserved.

iOS.Core.Animation笔记二.Motion

第二部分主要是关于动画的

7. Implicit Animations 隐式动画

隐式动画就是,当你修改CALayer一个支持动画的属性时,这个变换的效果不是立刻体现在屏幕上,而是使用一个平滑的动画从原来值过度到新的值。这是一个默认的行为,根本不需要开发做任何事;

CATransaction类用于管理变换,你不能通过+alloc和-init方法来创建他,而是应该通过+begin和+commit来提交变换,或者获取当前正在执行的变换。通过+setAnimationDuration方法设置变换的持续时间,另外可以通过+animationDuration方法获取当前变换的持续时间。

Core Animation通过run loop的迭代循环来开始一个变换,默认的持续时间是0.25秒。通过+setAnimationDuration:方法设置持续时间,附带的也会影响到其他当前发生的变换动画。

CATransaction提供了+setCompletionBlock:用于设置动画结束后执行,并且他的默认持续时间也是0.25秒。

CALayer的动画属性被默认开启,但是UIView则不是。这需要了解一下隐式动画的实现方式,当有CALayer的任意属性被修改时:

  1. 调用自己的-actionForKey:方法,并且传入当前属性的名称;返回对象(CAAction协议对象)并执行,传入参数分别是属性名、layer,dict;
  2. layer检查是否有delegate实现了CALayerDelegate协议中定义的-actionForLayer:forKey方法,有的话执行并返回;
  3. 如果上面没有,则检查layer自己的actions有没有属性对应的CAAction;
  4. 如果上面也没有,则检查layer自己的style有没有属性对应的CAAction;
  5. 如果上面也没有,layer会调用-defaultActionForKey:方法,找到那些默认定义的属性及其action;

而在UIView中,每个UIView都是他layer的delegate,并且提供了-actionForLayer:forKey方法的实现。不在动画block中时(应该是指+beginAnimations:context和+commitAnimations之间),该方法永远返回ni,而如果在动画block中时则返回非nil。

展现层和模型层

iOS中,屏幕每秒钟绘制60次。如果一个动画的持续时间超过60分之1秒,那么Core Animation在新值展现到屏幕之前的过程中,需要合成计算好几次。这意味着CALayer必须要保持一个用于展示的当前值。

这个用于展示的当前值被保存在一个叫做展现层(presentation layer)的地方,我们可以通过-presentationLayer方法访问。注意这个属性只有在layer被第一次绘制到屏幕上以后才被创建。

以下两种情况你需要用到这个展现层

  1. 你在实现一个基于时间轴的动画
  2. 你需要动画中的layer响应用户输入,比如-hitTest:判断layer是否被点击时,展现层才是layer当前的位置所在

————————————————————————————————————————

8. 显式动画

Basic Animations

使用显示动画只会修改persetation layer的值,要想看到正常的效果需要同时修改model layer的属性值。

Keyframe Animations

CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"backgroundColor";
animation.duration = 2.0;
animation.values = @[
                     (__bridge id)[UIColor blueColor].CGColor,
                     (__bridge id)[UIColor redColor].CGColor,
                     (__bridge id)[UIColor greenColor].CGColor,
                     (__bridge id)[UIColor blueColor].CGColor
                     ];

//apply animation to layer
[self.colorLayer addAnimation:animation forKey:nil];

通过path属性指定运动路径,rotationMode指定运动中物体朝向

//create the keyframe animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
animation.duration = 4.0;
animation.path = bezierPath.CGPath;
animation.rotationMode = kCAAnimationRotateAuto;
[shipLayer addAnimation:animation forKey:nil];

Virtual Properties

transform.rotation
transform.scale 不是真实存在的属性,但是可以在animation使用 不知道还有没有更多?

Animation Group 动画组

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = @[animation1,animation2];
animationGroup.duration = 4.0;
// animation1和animation2可以任何的CAAnimation的子类型 更多动画组的示例可以参考[objc.io的issue-12-1](http://objccn.io/issue-12-1/)

Transition

CATransition有2个重要的属性type和subType, type定义动画的方式,如下: kCATransitionFade kCATransitionMoveIn kCATransitionPush kCATransitionReveal subType定义动画出现的方向,如下: kCATransitionFromRight kCATransitionFromLeft kCATransitionFromTop kCATransitionFromBottom

————————————————————————————————————————

9. Layer Time

CAMediaTiming

CAMeidaTiming Protocol几个重要的属性:

duration 			// 每次重复的持续时间
repeatCount 	// 重复的次数   = HUGE_VALF 无限循环
repeatDuration // 总重复的时间
autoreverses 	// 是否自动倒序播放动画

beginTime 		// 动画开始的延迟时间
speed				// 动画的播放速度,默认=1.0
timeOffset		// 动画开始后xx时间才显示出来,也就是中途展示一个动画的偏移时间

fillMode

填充动画已经结束到没开始这段时间内展现层的效果,可选值如下:

kCAFillModeForwards
	kCAFillModeBackwards
	kCAFillModeBoth
	kCAFillModeRemoved #### Local Time 每个Layer和Animation都有自己的local time,如果要同步多个不同speed的animation,我们需要使用以下方法做转换:

- (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l;
- (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;

Pause, Rewind, Fast-Forward

通过设置CALayer的speed(实际上是CAMediaTiming的speed,CALayer实现了该protocol)可以控制动画的暂停(speed=0),倒退(speed设置为负数)和快进(speed设置大于1); 可以通过类似方法控制main window的速度

self.window.layer.speed = 100;
Manual Animation

可以通过speed和timeOffset手动控制动画的播放。首先speed暂停动画的播放,然后再设置timeOffset设置动画前进或者后退。

————————————————————————————————————————

10. Easing

CAMediaTimingFunction

// 1. 系统提供的5种
+ (id)functionWithName:(NSString *)name
kCAMediaTimingFunctionDefault; 
kCAMediaTimingFunctionEaseIn; 
kCAMediaTimingFunctionEaseInEaseOut; 
kCAMediaTimingFunctionEaseOut; 
kCAMediaTimingFunctionLinear;

// 2. 通过自定义贝塞尔曲线的两个control point生成(在0-1范围内)
+ (id)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y

CAKeyframeAnimation可以通过timingFunctions属性来支持每个关键帧之间的easing

————————————————————————————————————————

comments powered by Disqus