CAKeyframeAnimation——关键帧动画
关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:
–CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
–
属性说明:
–values:上述的NSArray对象。里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
–path:可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,那么values将被忽略
–keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的
CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation
具体的关键帧实例如下:
实例一:设置改变的属性值为透明度opacity,触摸屏幕时,动画开始执行,动画执行过程中,动画的透明度逐渐变浅.结束时透明度恢复原状。
代码如下:
//声明属性
#import "ViewController.h" @interface ViewController () @property (strong,nonatomic)CALayer *subLayer; //声明核心动画子层 @end
//创建核心动画子层
- (void)viewDidLoad {
[super viewDidLoad];
//创建子层
self.subLayer = [CALayer layer];
//设置子层大小
self.subLayer.bounds = CGRectMake(0, 0, 100, 100);
//设置子层的位置
self.subLayer.position = CGPointMake(100, 100);
//设置子层的背景颜色
self.subLayer.backgroundColor = [[UIColor redColor]CGColor];
//添加子层到根层
[self.view.layer addSublayer:self.subLayer];
}
//处理触摸事件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//创建关键帧动画
CAKeyframeAnimation *keyframe = [[CAKeyframeAnimation alloc]init];
//设置变化属性值为透明度
keyframe.keyPath = @"opacity"; //设置每一帧动画的透明度时刻值
keyframe.values = @[@1.0,@0.5,@0.0,@0.5,@1.0];
//设置动画持续事件
keyframe.duration = 1.0f;
//添加动画到子层
[self.subLayer addAnimation:keyframe forKey:@"keyAnimation"]; //forkey:的参数可以自己设置,就是一个标示符,区别开其他的动画
}
演示结果:
开始时: 中间某一时刻: 结束时:



实例二:设置改变的属性值为位置position,当在屏幕上连续触摸5个点时,动画开始按照这个5个点的连接直线运行。等到结束时,动画就停在最终的位置上,不在恢复原状。
代码如下:
//声明属性
#import "ViewController.h" #define MAX_CLICKED_NUM 4 //触摸的最大次数 @interface ViewController () @property (strong,nonatomic)NSMutableArray *points; //用于存放触摸屏幕的次数 @property (strong,nonatomic)CALayer *subLayer;//声明核心动画子层 @end
//创建核心动画子层
- (void)viewDidLoad {
[super viewDidLoad];
//初始化
self.points = [NSMutableArray array];
//创建子层
self.subLayer = [CALayer layer];
self.subLayer.bounds = CGRectMake(0, 0, 100, 100);
self.subLayer.position = CGPointMake(100, 100);
self.subLayer.backgroundColor = [[UIColor redColor]CGColor];
//添加子层到根层
[self.view.layer addSublayer:self.subLayer];
}
//触摸事件的处理(如果触摸次数不够5次,就存储起来,达到5次时,创建帧动画,并开始动画)
//触摸事件的处理
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//获取当前触摸点
CGPoint location = [[touches anyObject]locationInView:self.view];
//判断当前的点的个数
if (self.points.count < MAX_CLICKED_NUM)
{
//添加当前点
[self.points addObject:[NSValue valueWithCGPoint:location]];
}
else
{
//创建关键帧动画
CAKeyframeAnimation *keyanimation = [[CAKeyframeAnimation alloc]init];
//设置该变量为位置position
keyanimation.keyPath = @"position";
//设置每一帧动画的位置值
keyanimation.values = self.points;
//设置动画持续时间
keyanimation.duration = 3.0f;
//设置动画不在恢复原状
keyanimation.removedOnCompletion = NO;
keyanimation.fillMode = kCAFillModeForwards;
//设置代理
keyanimation.delegate = self;
//添加动画到层
[self.subLayer addAnimation:keyanimation forKey:@"keyanimation"];
}
}
//实现动画的协议方法
#pragma mark -动画代理方法
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//关闭隐式动画
[CATransaction begin];
[CATransaction setDisableActions:YES];
//停留在最后的位置
self.subLayer.position = [[self.points lastObject]CGPointValue];
//提交动画事物
[CATransaction commit];
//删除上一次动画结束后保存的所有的数据
[self.points removeAllObjects];
}
演示结果:点击5次后,运动过程不好捕捉,就不截图了
起点: 终点:

实例三:设置改变的属性值为位置position,在屏幕上绘制一条线,绘制结束后,动画就沿着这条线开始动画。等到结束时,动画就停在最终的位置上,不在恢复原状。
代码如下:
//声明属性
#import "ViewController.h" @interface ViewController () @property (strong,nonatomic)CALayer *subLayer; //声明核心动画子层用作动画层 @property (assign,nonatomic)CGMutablePathRef path; //声明可变的绘图路径 @property (strong,nonatomic)CALayer *DrawLayer; //声明核心动画子层用来绘图层 @end
//创建两个核心动画子层,一个用来绘制运行线路,另一个用来当作动画层
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建绘图子层
self.DrawLayer = [CALayer layer];
self.DrawLayer.bounds = self.view.bounds;
self.DrawLayer.position = CGPointMake(0, 0);
self.DrawLayer.anchorPoint = CGPointMake(0, 0);
self.DrawLayer.backgroundColor = [[UIColor whiteColor]CGColor]; //设置绘图子层的代理,它会调用协议中的绘图方法
self.DrawLayer.delegate = self;
//添加绘图子层
[self.view.layer addSublayer:self.DrawLayer];
//创建动画子层
self.subLayer = [CALayer layer];
self.subLayer.bounds = CGRectMake(0, 0, 100, 100);
self.subLayer.position = CGPointMake(100, 100);
self.subLayer.backgroundColor = [[UIColor redColor]CGColor];
//添加动画子层
[self.view.layer addSublayer:self.subLayer];
}
//处理触摸点击事件,设置绘制线路径的起点
//触摸点击事件的处理
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//获取当前触摸点
CGPoint location = [[touches anyObject]locationInView:self.view];
//创建路经
self.path = CGPathCreateMutable();
//将当前点加到路径中去
CGPathMoveToPoint(self.path, NULL, location.x, location.y);
}
//处理触摸移动事件,绘制一条路径线到终点,此时绘图子层调用setNeedDisplay方法绘图
//触摸移动事件的处理
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//获取当前触摸点
CGPoint location = [[touches anyObject]locationInView:self.view];
//将当前点加到路径中去
CGPathAddLineToPoint(self.path, NULL, location.x, location.y);
//让绘图子层绘图
[self.DrawLayer setNeedsDisplay];
}
//处理触摸结束事件,绘制线路径结束后,创建帧动画,设置相关属性并执行动画
//触摸结束事件的处理
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//创建帧动画
CAKeyframeAnimation *keyAnimation = [[CAKeyframeAnimation alloc]init];
//设置改变属性值为位置position
keyAnimation.keyPath = @"position";
//设置动画路径为绘制的路径
keyAnimation.path = self.path;
//设置动画持续时间
keyAnimation.duration = 3.0f;
//设置动画结束时保持不变,不在恢复原状
keyAnimation.removedOnCompletion = NO;
keyAnimation.fillMode = kCAFillModeForwards;
//设置帧动画代理
keyAnimation.delegate = self;
//添加帧动画到动画子层
[self.subLayer addAnimation:keyAnimation forKey:@"keyAnimation"];
}
//实现帧动画协议方法,动画结束后,释放绘制路径
#pragma mark -动画代理方法
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//释放路径
CGPathRelease(self.path);
}
//重写绘图子层的绘图方法-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx,绘图子层代理会调用它绘图
#pragma mark -UILayer画图方法
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
//添加路径
CGContextAddPath(ctx, self.path);
//设置颜色
CGContextSetStrokeColorWithColor(ctx, [[UIColor blueColor]CGColor]);
//绘路径
CGContextDrawPath(ctx, kCGPathStroke);
}
运行结果如下:只给出起始位置和结束位置截图,动画过程不好捕捉,就不给出截图了
开始时位置: 绘制路径后,动画沿路径运行结束位置:

来源:https://www.cnblogs.com/XYQ-208910/p/4886488.html