核心动画框架 QuartzCore
CALayer就是UIView上的图层,很多的CALayer组成了UIView。
CALayer与UIView是两个完全不同的类
UIView动画就是简单动画,可以实现改变,偏移,形变,翻转,旋转,翻页
QuartzCore.framework:
NSObject
CAAnimation:
CAAnimationGroup: 并行动画
CATransition:
CAPropertyAnimation: 属性动画
CABasicAnimation:
CAKeyframeAnimation:
大家都知道在iOS中实现一个动画相当简单,只要调用UIView的块代码即可实现一个动画效果,这在其他系统开发中基本不可能实现。
使用上面UIView封装的方法进行动画设置固然十分方便,但是具体动画如何实现我们是不清楚的。
这里就需要了解iOS的核心动画Core Animation(包含在Quartz Core框架中)。在iOS中核心动画分为几类:基础动画、关键帧动画、动画组、转场动画。各个类的关系大致如下:
CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议。
CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用。
1-1 CABasicAnimation:基础动画,通过属性修改进行动画参数控制,只有初始状态和结束状态。
1-2 CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制。CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行。
CATransition:转场动画,主要通过滤镜进行动画效果设置。重要属性type : 转场类型,subType: 方向
基础动画、关键帧动画都属于属性动画,就是通过修改属性值产生动画效果,开发人员只需要设置fromValue初始值和toValue结束值,中间的过程动画(又叫“补间动画”)由系统自动计算产生。
和基础动画不同的是关键帧动画可以设置多个属性值,每两个属性中间的补间动画由系统自动完成,因此从这个角度而言基础动画又可以看成是有两个关键帧的关键帧动画。
CABasicAnimation基础动画
如果不使用UIView封装的方法,动画创建一般分为以下几步:
1.初始化动画并设置动画属性
2.设置动画属性初始值(可以省略)、结束值以及其他动画属性
3.给图层添加动画
#import "KCMainViewController.h"
@interface KCMainViewController (){
CALayer *_layer;
}
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置背景(注意这个图片其实在根图层)
UIImage *backgroundImage=[UIImage imageNamed:@"background.jpg"];
self.view.backgroundColor=[UIColor colorWithPatternImage:backgroundImage];
//自定义一个图层
_layer=[[CALayer alloc]init];
_layer.bounds=CGRectMake(0, 0, 10, 20);
_layer.position=CGPointMake(50, 150);
_layer.contents=(id)[UIImage imageNamed:@"petal.png"].CGImage;
[self.view.layer addSublayer:_layer];
}
#pragma mark 点击事件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=touches.anyObject;
CGPoint location= [touch locationInView:self.view];
//创建并开始动画
[self translatonAnimation:location];
}
#pragma mark 移动动画
-(void)translatonAnimation:(CGPoint)location{
//1.创建动画并指定动画属性
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"position"];
//2.设置动画属性初始值和结束值
// basicAnimation.fromValue=[NSNumber numberWithInteger:50];//可以不设置,默认为图层初始状态
basicAnimation.toValue=[NSValue valueWithCGPoint:location];
//设置其他动画属性
basicAnimation.duration=5.0;//动画时间5秒
//basicAnimation.repeatCount=HUGE_VALF;//设置重复次数,HUGE_VALF可看做无穷大,起到循环动画的效果
// basicAnimation.removedOnCompletion=NO;//运行一次是否移除动画
//3.添加动画到图层,注意key相当于给动画进行命名,以后获得该动画时可以使用此名称获取
[_layer addAnimation:basicAnimation forKey:@"KCBasicAnimation_Translation"];
}
@end
上面实现了一个基本动画效果,但是这个动画存在一个问题:动画结束后动画图层回到了原来的位置,当然是用UIView封装的方法是没有这个问题的。如何解决这个问题呢?
原因:
图层动画的本质就是将图层内部的内容转化为位图经硬件操作形成一种动画效果,其实图层本身并没有任何的变化。上面的动画中图层并没有因为动画效果而改变它的位置(对于缩放动画其大小也是不会改变的),所以动画完成之后图层还是在原来的显示位置没有任何变化,如果这个图层在一个UIView中你会发现在UIView移动过程中你要触发UIView的点击事件也只能点击原来的位置(即使它已经运动到了别的位置),因为它的位置从来没有变过。
解决方法之一:在动画完成之后重新设置它的位置。
#import "KCMainViewController.h"
@interface KCMainViewController (){
CALayer *_layer;
}
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置背景(注意这个图片其实在根图层)
UIImage *backgroundImage=[UIImage imageNamed:@"background.jpg"];
self.view.backgroundColor=[UIColor colorWithPatternImage:backgroundImage];
//自定义一个图层
_layer=[[CALayer alloc]init];
_layer.bounds=CGRectMake(0, 0, 10, 20);
_layer.position=CGPointMake(50, 150);
_layer.contents=(id)[UIImage imageNamed:@"petal.png"].CGImage;
[self.view.layer addSublayer:_layer];
}
#pragma mark 点击事件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=touches.anyObject;
CGPoint location= [touch locationInView:self.view];
//创建并开始动画
[self translatonAnimation:location];
}
#pragma mark 移动动画
-(void)translatonAnimation:(CGPoint)location{
//1.创建动画并指定动画属性
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"position"];
//2.设置动画属性初始值和结束值
// basicAnimation.fromValue=[NSNumber numberWithInteger:50];//可以不设置,默认为图层初始状态
basicAnimation.toValue=[NSValue valueWithCGPoint:location];
//设置其他动画属性
basicAnimation.duration=5.0;//动画时间5秒
//basicAnimation.repeatCount=HUGE_VALF;//设置重复次数,HUGE_VALF可看做无穷大,起到循环动画的效果
// basicAnimation.removedOnCompletion=NO;//运行一次是否移除动画
basicAnimation.delegate=self;
//(修改)存储当前位置在动画结束后使用(结束后固定其位置)
[basicAnimation setValue:[NSValue valueWithCGPoint:location] forKey:@"KCBasicAnimationLocation"];