iOS.Core.Animation笔记二.Motion
13 May 2014第二部分主要是关于动画的
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的任意属性被修改时:
- 调用自己的-actionForKey:方法,并且传入当前属性的名称;返回对象(CAAction协议对象)并执行,传入参数分别是属性名、layer,dict;
- layer检查是否有delegate实现了CALayerDelegate协议中定义的-actionForLayer:forKey方法,有的话执行并返回;
- 如果上面没有,则检查layer自己的actions有没有属性对应的CAAction;
- 如果上面也没有,则检查layer自己的style有没有属性对应的CAAction;
- 如果上面也没有,layer会调用-defaultActionForKey:方法,找到那些默认定义的属性及其action;
而在UIView中,每个UIView都是他layer的delegate,并且提供了-actionForLayer:forKey方法的实现。不在动画block中时(应该是指+beginAnimations:context和+commitAnimations之间),该方法永远返回ni,而如果在动画block中时则返回非nil。
- UIView的layer不支持隐式动画,有几种方法让UIView的属性也支持动画:
- 使用UIView的动画方法
- 子类化UIView并且重载-actionForLayer:forKey:方法
- 创建一个显式动画
- 自主Layer控制动画的方式:
- layer的delegate实现-actionForLayer:forKey:
- 提供actions
展现层和模型层
iOS中,屏幕每秒钟绘制60次。如果一个动画的持续时间超过60分之1秒,那么Core Animation在新值展现到屏幕之前的过程中,需要合成计算好几次。这意味着CALayer必须要保持一个用于展示的当前值。
这个用于展示的当前值被保存在一个叫做展现层(presentation layer)的地方,我们可以通过-presentationLayer方法访问。注意这个属性只有在layer被第一次绘制到屏幕上以后才被创建。
以下两种情况你需要用到这个展现层
- 你在实现一个基于时间轴的动画
- 你需要动画中的layer响应用户输入,比如-hitTest:判断layer是否被点击时,展现层才是layer当前的位置所在
————————————————————————————————————————
8. 显式动画
Basic Animations
-
CAAnimation 实现了CAAction和CAMediaTiming协议,另外有3个重要的属性
- removeOnCompletion 是否动画完成自动删除,default=YES
- timing fuction
- delegate 反馈动画的状态
-
CAPropertyAnimation 通过keyPath针对单个属性值,keyPath可以是含有.符号的多层属性,可以使layer的属性,也可以使layer子元素的属性或者虚拟属性,点击查看更多支持的键路径列表
-
CABasicAnimation 继承了CAPropertyAnimation并添加了3个属性:fromValue/toValue/byValue,他们同时不能超过2个有值,即不能3个同时有值:
- fromValue/toValue有值,fromValue ~ toValue
- fromValue/byValue有值,fromValue ~ byValue
- byValue/toValue有值,(toValue-byValue) ~ toValue
- fromValue有值,fromValue ~ (current presetation)
- toValue有值,(current presetation) ~ toValue
- byVallue有值,(current presetation) ~ (byValue + current presetation)
- all nil,(previous) ~ (current) in presetation layer
使用显示动画只会修改persetation layer的值,要想看到正常的效果需要同时修改model layer的属性值。
- CAAnimationDelegate CAAnimation的delegate实现了这个协议,他有2个方法-animationDidStop:finished:和-animationDidStart:
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
————————————————————————————————————————