CALayer与UIView的关系
在iOS中,你能看得见摸得着的东西基本上都是UIView。
在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。
当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。
换句话说,UIView本身不具备显示的功能,是它内部layer才有显示功能。
CALayer的基本属性
CALayer *layer = [CALayer layer];
//layer的大小
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.backgroundColor = [UIColor redColor].CGColor;
//位置
layer.position = CGPointZero;
//锚点
layer.anchorPoint = CGPointZero;
//形变,三维的,uiview是二维
self.iconView.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
[self.view.layer addSublayer:layer];
View和CALayer的Frame,bounds,center 映射
一个 Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的.
一个 View 的 frame 只是简单的返回 Layer的 frame,View 的 Center 和 Bounds 只是直接返回layer 对应的 Position 和 Bounds。
View中frame getter方法,bounds和center,UIView并没有做什么工作;它只是简单的各自调用它底层的CALayer的frame,bounds和position方法。
CALayerd 的 position和anchorPoint的作用
position用来设置CALayer在父层中的位置,以父层的左上角为原(0, 0)。
anchorPoint 称为“定位点”、“锚点”,决定着CALayer身上的哪个点会在position属性所指的位置。以自己的左上角为原点(0, 0),它的x、y取值范围都是0~1,默认值为中心点(0.5, 0.5)。
CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.backgroundColor = [UIColor redColor].CGColor;
layer.anchorPoint = CGPointZero;
layer.position = CGPointMake(0 , 0);
[self.view.layer addSublayer:layer];
CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.backgroundColor = [UIColor redColor].CGColor;
layer.anchorPoint = CGPointMake(0, 1);
layer.position = CGPointMake(100 , 100);
[self.view.layer addSublayer:layer];
- 绿色箭头所指的就是锚点和position重合的位置。
Core Animation核心动画结构图。
其中灰色虚线表示继承关系,红色表示遵守协议。
核心动画中所有类都遵守CAMediaTiming协议。
CAAnaimation是个抽象类,不具备动画效果,必须用它的子类才有动画效果。
CAAnimationGroup和CATransition才有动画效果,CAAnimationGroup是个动画组,可以同时进行缩放,旋转(同时进行多个动画)。
CATransition是转场动画,界面之间跳转(切换)都可以用转场动画。
CAPropertyAnimation也是个抽象类,本身不具备动画效果,只有子类才有。
CABasicAnimation和CAKeyframeAnimation:
CABasicAnimation基本动画,做一些简单效果。
CAKeyframeAnimation帧动画,做一些连续的流畅的动画。
CAAnimation 抽象类的一些属性
CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类。
fillMode属性的设置:
kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态
速度控制函数(CAMediaTimingFunction):
kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
CAAnimation在分类中定义了代理方法
@protocol CAAnimationDelegate <NSObject>
@optional
/* Called when the animation begins its active duration. */
- (void)animationDidStart:(CAAnimation *)anim;
/* Called when the animation either completes its active duration or
* is removed from the object it is attached to (i.e. the layer). 'flag'
* is true if the animation reached the end of its active duration
* without being removed. */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end
CAPropertyAnimation
是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation。
属性keyPath,通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@“position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果,需要注意的是部分属性值是不支持动画效果的,以下是具有动画效果的keyPath:
//CATransform3D Key Paths : (example)transform.rotation.z
//rotation.x
//rotation.y
//rotation.z
//rotation 旋转
//scale.x
//scale.y
//scale.z
//scale 缩放
//translation.x
//translation.y
//translation.z
//translation 平移
//CGPoint Key Paths : (example)position.x
//x
//y
//CGRect Key Paths : (example)bounds.size.width
//origin.x
//origin.y
//origin
//size.width
//size.height
//size
//opacity
//backgroundColor
//cornerRadius
//borderWidth
//contents
//Shadow Key Path:
//shadowColor
//shadowOffset
//shadowOpacity
//shadowRadius
CABasicAnimation——基本动画
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"bounds";
anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
anim.duration = 2.0;
/**让图层保持动画执行完毕后的状态**/
// 动画执行完毕后不要删除动画
anim.removedOnCompletion = NO;
// 保持最新的状态
anim.fillMode = kCAFillModeForwards;
// 3.添加动画
[self.layer addAnimation:anim forKey:@"baseAnimal"];
- 如果fillMode = kCAFillModeForwards同时removedOnComletion = NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
CAKeyframeAnimation——关键帧动画
关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:
CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"position";
NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(200, 100)];
NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue *v5 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
anim.values = @[v1, v2, v3, v4,v5];
anim.duration = 2.1;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
[self.redView.layer addAnimation:anim forKey:nil];
CAKeyframeAnimation * ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(130, 200, 100, 100));
ani.path = path;
CGPathRelease(path);
ani.duration = 4.0;
ani.removedOnCompletion = NO;
ani.fillMode = kCAFillModeForwards;
[self.centerShow.layer addAnimation:ani forKey:@"PostionKeyframePathAni"];
CAAnimationGroup——动画组
动画组,是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。
// 1.创建旋转动画对象
CABasicAnimation *rotate = [CABasicAnimation animation];
rotate.keyPath = @"transform.rotation";
rotate.toValue = @(M_PI);
// 2.创建缩放动画对象
CABasicAnimation *scale = [CABasicAnimation animation];
scale.keyPath = @"transform.scale";
scale.toValue = @(0.0);
// 3.平移动画
CABasicAnimation *move = [CABasicAnimation animation];
move.keyPath = @"transform.translation";
move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
// 4.将所有的动画添加到动画组中
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[rotate, scale, move];
group.duration = 2.0;
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[self.myvie.layer addAnimation:group forKey:nil];
CATransition——转场动画
CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点。
UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果。
属性说明:
过渡效果设置
// 转场动画
CATransition *anim = [CATransition animation];
// type的enum值如下:
// kCATransitionFade 渐变
// kCATransitionMoveIn 覆盖
// kCATransitionPush 推出
// kCATransitionReveal 揭开
anim.type = @"pageCurl";
// subtype的enum值如下:
// kCATransitionFromRight 从右边
// kCATransitionFromLeft 从左边
// kCATransitionFromTop 从顶部
// kCATransitionFromBottom 从底部
anim.subtype = kCATransitionFromRight;
anim.duration = 0.5;
// anim.startProgress = 0.0;
//
// anim.endProgress = 0.5;
[self.view.layer addAnimation:anim forKey:nil];
CADisplayLink
CADisplayLink是一种以屏幕刷新频率触发的时钟机制,每秒钟执行大约60次左右。
CADisplayLink是一个计时器,可以使绘图代码与视图的刷新频率保持同步,而NSTimer无法确保计时器实际被触发的准确时间。
// 定义
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(hehe)];
// 添加到主循环队列
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode: NSRunLoopCommonModes];
- 了解CADisplayLink更多看这个http://www.jianshu.com/p/c35a81c3b9eb