Core Animation
一、Core Animation简介
(1)Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果
(2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
(3)Core Animation是直接作用在CALayer上的,并非UIView。
(4)什么是Core Animation?
CAAnimation可分为四种:
- CABasicAnimation
通过设定始末两点和动画时间,动画会沿着这两点进行移动。可以看做只有始末两点的特殊的CAKeyFrameAnimation。
- CAKeyframeAnimation
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame 和 动画的时间,动画会沿你设定的轨迹进行移动。
- CAAnimationGroup
Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时按顺序执行。
- CATransition
这个就是苹果帮开发者封装好的一些动画。
二、Core Animation的使用步骤
1.使用它需要先添加QuartzCore.framework框架和引入主头文件<QuartzCore/QuartzCore.h>
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
三、CAAnimation 的属性(多数动画的公共属性)
CoreAnimation - CAAnimation.h 中:
-
timingFunction:
定义动画的运动节奏,默认值是0(线性的)。比如是均匀变化(相同时间变化量相同)还是先快后慢,先慢后快还是先慢再快再慢。
动画的开始与结束的快慢,有五个预置分别为(下同):
* kCAMediaTimingFunctionLinear 线性,即匀速
* kCAMediaTimingFunctionEaseIn 先慢后快
* kCAMediaTimingFunctionEaseOut 先快后慢
* kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
* kCAMediaTimingFunctionDefault 实际效果是动画中间比较快.
-
removedOnCompletion:
BOOL值,默认YES。指当动画结束时,是否从渲染树移除动画。由这个属性可以看出,动画效果其实就是一个假象一个效果,动画并不会改变对象的frame。
CoreAnimation - CAMediaTiming.h 中:
-
repeatCount:
float,动画重复的次数。
-
autoreverses:
BOOL值,默认NO。当动画结束时,是否倒着重复一遍动画。
-
fillMode:
定义对象在活动时间以外的行为(动画结束后的行为),可以强制让对象的行为(动画)停留在活动结束时的某一刻(前、后、中间)或者移除对象的行为(动画)。
强制设置对象的行为:
* NSString * const kCAFillModeForwards 结束前
* NSString * const kCAFillModeBackwards 结束后
* NSString * const kCAFillModeBoth 中间
* NSString * const kCAFillModeRemoved 移除行为
注意:如果想要规定动画停止时的行为,必须同时设置一下两属性:
removedOnCompletion 和 fillMode
@interface CAPropertyAnimation : CAAnimation
---> CABasicAnimation 和 CAKeyframeAnimation 公有的属性
-
additive:
默认NO。当置YES时,新设置的animation.values的值将被『附加』到目前描述Layer的属性的值上,以产生新的描述值。(而不是取代当前值)
e.g.输入框输入错误动画--下面关键帧动画的实例。
三、动画类型
1.CATransition过渡动画(转场动画)
CATransition
是CAAnimation
的子类,实际上是苹果帮开发者封装好的一些动画,专门用于做转场动画。(能够为层和视图控制器提供移出屏幕和移入屏幕的动画效果)
-
设置转场动画的过程
a.创建转场动画:
[CATransition animation]
b.设置动画属性值
c.添加到需要转场动画的图层上
[layer addAnimation:animation forKey:nil]
-
CATransition动画属性:
-
type
:动画过渡类型
type的值:转场动画的类型(NSString *type)
动画类型 说明 对应常量 是否支持方向设置 公开API fade 淡出效果 kCATransitionFade 是 movein 新视图移动到旧视图上 kCATransitionMoveIn 是 push 新视图推出旧视图 kCATransitionPush 是 reveal 移开旧视图显示新视图 kCATransitionReveal 是 私有API ---- 私有API只能通过字符串访问,如@"cube" cube 立方体翻转效果 无 是 oglFlip 翻转效果 无 是 suckEffect 收缩效果 无 否 rippleEffect 水滴波纹效果 无 否 pageCurl 向上翻页效果 无 是 pageUnCurl 向下翻页效果 无 是 cameralIrisHollowOpen 摄像头打开效果 无 否 cameraIrisHollowClose 摄像头关闭效果 无 否 下面这个几个用在UIView的setAnimationTransition方法中
13 UIViewAnimationTransitionCurlDown, //下翻页
14 UIViewAnimationTransitionCurlUp, //上翻页
15 UIViewAnimationTransitionFlipFromLeft, //左翻转
16 UIViewAnimationTransitionFlipFromRight, //右翻转
-
subtype
:动画过渡方向
subtype的值:转场动画的方向(NSString *subtype)
从某个方向开始:
fromLeft
,fromRight
,fromTop
,fromBottom
也可以通过输入上方的字符串来调用这些方法。
动画子类型 说明 kCATransitionFromRight 从右侧转场 kCATransitionFromLeft 从左侧转场 kCATransitionFromTop 从顶部转场 kCATransitionFromBottom 从底部转场
-
startProgress
:动画起点(在整体动画的百分比),默认值为0.0。必须小于等于结束点。
-
endProgress
:动画终点(在整体动画的百分比),默认值为1.0。必须大于等于开始点。
CATransition中endProgress:转场动画的终点(完整动画的百分之几)(float endProgress)
想要动画成功地停止在设置的点,需要同时设置动画的以下几个属性:
- animation.endProgress = 0.7;
- animation.fillmode = CAFillModeForwards 或 kCAFillModeBoth; //设置活动时间外的行为
- animation.removedOnCompletion = NO; //在动画执行完成时,是否被移除(默认是)
-
filter
:动画的滤镜(可选的)
CATransition中的filter:转场动画的滤镜(CIFiler *filter)
如果指定,那么指定的filter必须同时支持x和y,否则该filter将不起作用。默认值为nil。
如果设置了filter,那么,为layer设置的type和subtype属性将被忽略。
该属性只在iOS 5.0以及以后版本被支持。
-
CATransition转场动画的实际应用:
(1)视图切换
应用:用酷炫的动画效果实现单个UIImageView上切换不同图片
#import "ViewController.h" @interface ViewController () { NSInteger _count; } @property (nonatomic, weak) UIImageView *imageView; @end @implementation ViewController - (UIImageView *)imageView { if (!_imageView) { UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"%ld",_count]]]; imageView.frame = CGRectMake(20, 70, self.view.frame.size.width - 40, self.view.frame.size.width - 40); imageView.userInteractionEnabled = YES; [self.view addSubview:imageView]; _imageView = imageView; } return _imageView; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _count = 1; UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; //设置轻扫方向 leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft; [self.imageView addGestureRecognizer:leftSwipe]; UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; rightSwipe.direction = UISwipeGestureRecognizerDirectionRight; [self.imageView addGestureRecognizer:rightSwipe]; } //处理轻扫手势 - (void)swipeGesture:(UISwipeGestureRecognizer *)swipe { //转场动画 CATransition *animation = [CATransition animation]; //动画时间 animation.duration = 1.0f; //display mode, slow at beginning and end animation.timingFunction = UIViewAnimationCurveEaseInOut; //在动画执行完时是否被移除 animation.removedOnCompletion = NO; //过渡效果 animation.type = @"pageCurl"; //过渡方向 animation.subtype = kCATransitionFromRight; //暂时不知,感觉与Progress一起用的,如果不加,Progress好像没有效果 animation.fillMode = kCAFillModeForwards; //动画停止(在整体动画的百分比). animation.endProgress = 0.7; animation.startProgress = 0.5; if (swipe.direction == UISwipeGestureRecognizerDirectionLeft) { NSLog(@"向左"); _count++; //方向 animation.subtype = kCATransitionFromRight; } else if(swipe.direction == UISwipeGestureRecognizerDirectionRight) { NSLog(@"向右"); _count--; //方向 animation.subtype = kCATransitionFromLeft; } else if (swipe.direction == UISwipeGestureRecognizerDirectionUp) { NSLog(@"向上"); } else { NSLog(@"向下"); } //添加动画 [self.imageView.layer addAnimation:animation forKey:nil]; //重新修改图片 self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",_count]]; }
(2)控制器切换
2.CAKeyframeAnimation 关键帧动画
- 提供 「CALayer的始点、中间关键点、终点的位置」 或者 「一条路径」,动画会沿你设定的轨迹进行移动。
- 创建CAKeyframeAnimation需要用到『KeyPath』
- e.g. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];
支持CAKeyframeAnimation的keyPath:
注意:上面表格里面的key前面都需要加上transform
- 属性解析
-
values:是一个NSArray对象。里面的元素称为『关键帧』(keyframe)。动画对象会在指定的时间(duration)内,依次移动到values数组中的每一个关键帧。
-
path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。values和path是互斥的:如果你设置了path,那么values将被忽略。
-
keyTimes:该属性是一个数组,可以为每个关键帧(子路径AB,BC,CD)指定对应的时间点。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7。当keyTimes没有设置的时候,各个关键帧的时间是平分的。
-
timeFunctions:上方已提出,简单地说就是设置动画的快慢。
需要注意的是:若keyTimes未设置(各帧时间平分),timesFunctions选择匀速,此时意味着每一段动画都是匀速,而非意味着每一段动画的速度都是相同的。因为速度还取决与距离:时间相同、确定是匀速运动,但是距离不同,所以匀速但速度不同!
-
calculationMode:用来设定每两个关键帧中间的行为(包括重复第二次播放时,上次结尾和下次开头中间的转换是否连续),决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似。
calculationMode的值:
const kCAAnimationLinear //线性,默认
const kCAAnimationDiscrete //离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上 const kCAAnimationPaced //平均,keyTimes跟timeFunctions失效 const kCAAnimationCubic //平均,同上 const kCAAnimationCubicPaced //平均,同上
-
应用实例
(1)values:关键位置数组(设定几个关键点)
CALayer *layer = [CALayer layer]; layer.bounds = CGRectMake(0, 0, 100, 100); layer.backgroundColor = [UIColor redColor].CGColor; layer.position = self.view.center; [self.view.layer addSublayer:layer]; //关键帧动画 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"]; //动画时间 animation.duration = 5; //动画的关键部分 animation.values = @[@(10),@(30),@(80),@(300)]; #if 0 //关键帧动画 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; //动画时间 animation.duration = 5; //动画的关键部分 animation.values = @[[NSValue valueWithCGPoint:CGPointMake(10, 10)], [NSValue valueWithCGPoint:CGPointMake(200, 200)], [NSValue valueWithCGPoint:CGPointMake(200, 400)], [NSValue valueWithCGPoint:CGPointMake(10, 10)]]; #endif //动画的节奏 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; //原路返回 animation.autoreverses = YES; //停留在动画结束的位置 animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; //添加动画并且执行 [layer addAnimation:animation forKey:nil];
(2)path:关键路径(通过CGPath设定一条自定义的路线)
CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, 0, 100, 100); layer.backgroundColor = [UIColor redColor].CGColor; [self.view.layer addSublayer:layer]; //创建动画 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; //动画时间 animation.duration = 5; //设置动画次数 animation.repeatCount = MAXFLOAT; //恒定的速度运动 animation.calculationMode = kCAAnimationPaced; //创建一个路径 CGMutablePathRef path = CGPathCreateMutable(); #if 0 //椭圆 CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 400)); #endif //矩形 CGPathAddRect(path, NULL, CGRectMake(100, 100, 200, 400)); //设置动画的路径 animation.path = path; //释放path CGPathRelease(path); //执行动画 [layer addAnimation:animation forKey:@"key"]; //5秒移除动画 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [layer removeAnimationForKey:@"key"]; });
注意记得释放path
(3)加入购物车:用贝塞尔曲线,画一条『path』抛物线(CGMutablePathRef),让动画沿着抛物线走
关键点:坐标转换 + 贝尔塞曲线的绘制(起点、终点、控制点『前两点切线交点』) + 核心动画
- CGPoint point = [self convertPoint:sender.center toView:self.superview];
- CGPoint startPoint = [self.tableView convertPoint:point toView:self.view];
- CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);
Cell :
#import <UIKit/UIKit.h> typedef void(^CarButtonClick)(CGPoint point); @interface Cell : UITableViewCell - (void)setCarButtonClick:(CarButtonClick)hanlde; @end #import "Cell.h" @interface Cell () { CarButtonClick _carButtonClick; } - (IBAction)buttonClick:(UIButton *)sender; @end @implementation Cell - (void)awakeFromNib { self.selectionStyle = UITableViewCellSelectionStyleNone; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } - (void)setCarButtonClick:(CarButtonClick)hanlde { _carButtonClick = hanlde; } - (IBAction)buttonClick:(UIButton *)sender { #pragma mark 坐标转换第一步 //按钮中心点转化为tableView的坐标系,返回一个新的坐标点 CGPoint point = [self convertPoint:sender.center toView:self.superview]; NSLog(@"%@",NSStringFromCGPoint(point)); //回调 if (_carButtonClick) { _carButtonClick(point); } } @end
ViewController 中 tableView的关键设置
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { Cell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; [cell setCarButtonClick:^(CGPoint point) { //起点 #pragma mark 坐标转换第二步 //把point转化为self.view的坐标系 CGPoint startPoint = [self.tableView convertPoint:point toView:self.view]; //NSLog(@"%@",NSStringFromCGPoint(startPoint)); //终点 CGPoint endPoint = _carCenter; //控制点(起点和终点切线交点) CGPoint controlPoint = CGPointMake(endPoint.x, startPoint.y); //创建一个物体 CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, 0, 30, 30); layer.position = startPoint; layer.backgroundColor = [UIColor redColor].CGColor; layer.cornerRadius = 15; [self.view.layer addSublayer:layer]; CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; animation.duration = 3; //坐标停留在终点 animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; //设置代理 animation.delegate = self; //创建一个二次贝塞尔曲线 CGMutablePathRef path = CGPathCreateMutable(); //设置起点 CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y); //(cpx,cpy)表示控制点 (x,y)终点 CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y); //设置曲线路径 animation.path = path; //执行动画 [layer addAnimation:animation forKey:nil]; //释放 CGPathRelease(path); }]; return cell; } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { NSLog(@"动画完成"); }
(4)输入框输入错误动画:设置简单的『values』,使其来回抖动
- animation.additive = YES;
#import "ViewController.h" @interface ViewController () { UITextField *_textField; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _textField = [[UITextField alloc] initWithFrame:CGRectMake(90, 80, 200, 40)]; _textField.borderStyle = UITextBorderStyleRoundedRect; [self.view addSubview:_textField]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"]; animation.duration = 0.2; animation.values = @[@(-5),@(0),@(5),@(0),@(-5)]; //additive 属性为 YES 能够在原属性值的基础上,附加values设置的值上去,产生新的描述结果。 animation.additive = YES; // animation.repeatCount = 2; [_textField.layer addAnimation:animation forKey:nil]; } @end
(5)视图抖动效果:角度转换为弧度,在Z轴上添加旋转。
移动改x或y轴,旋转改z轴。
- animation.values = @[@(kToRadian(-5)), @(kToRadian(0)), @(kToRadian(5)), @(kToRadian(0)), @(kToRadian(-5))]; //弧度
#import "ViewController.h" //角度转化为弧度 #define kToRadian(r) (M_PI/180*(r)) //返回两个值的最小值 #define kMin(a,b) ((a)>(b)?(b):(a)) @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIView *v = [[UIView alloc] initWithFrame:CGRectMake(90, 90, 100, 100)]; v.backgroundColor = [UIColor redColor]; v.layer.cornerRadius = 10; [self.view addSubview:v]; UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressHandle:)]; [v addGestureRecognizer:longPress]; } - (void)longPressHandle:(UILongPressGestureRecognizer *)longPress { //长按开始执行动画 if (longPress.state == UIGestureRecognizerStateBegan) { CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; //动画时间 animation.duration = 0.2; //动画次数 animation.repeatCount = MAXFLOAT; //弧度 animation.values = @[@(kToRadian(-5)), @(kToRadian(0)), @(kToRadian(5)), @(kToRadian(0)), @(kToRadian(-5))]; [longPress.view.layer addAnimation:animation forKey:@"key"]; //五秒后移除动画 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [longPress.view.layer removeAnimationForKey:@"key"]; }); } }
(6)点赞动画
- (IBAction)buttonClick:(UIButton *)sender { sender.selected = !sender.selected; //比例变化 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; animation.duration = 0.5; //👍 if (sender.selected) { //比例变化 animation.values = @[@(1.2),@(2),@(1)]; } //取消👍 else { //比例变化 animation.values = @[@(0.8),@(0.2),@(1)]; } //执行动画 [sender.layer addAnimation:animation forKey:nil]; }
3.CABasicAnimation基本动画(隐式动画)
- 属性分析:三个属性都是可选的,且至少一个不为nil。动画加点不为nil的两点之间。
-
三个属性:fromValue(起点)、toValue(终点)、byValue(附加值)
- 六种情况:
* - both `fromValue' and `toValue' non-nil. Interpolates between `fromValue' and `toValue'.
* - `fromValue' and `byValue' non-nil. Interpolates between `fromValue' and `fromValue' plus `byValue'.
* - `byValue' and `toValue' non-nil. Interpolates between `toValue' minus `byValue' and `toValue'.
* - `fromValue' non-nil. Interpolates between `fromValue' and the current presentation value of the property.
* - `toValue' non-nil. Interpolates between the layer's current value of the property in the render tree and `toValue'.
* - `byValue' non-nil. Interpolates between the layer's current value of the property in the render tree and that plus `byValue'.
- 支持CABasicAnimation的keyPath:
包括支持CAKeyframeAnimation的keyPath
以及:
opacity = 透明度
margin
zPosition
backgroundColor 背景颜色
cornerRadius 圆角
borderWidth
bounds
contents
contentsRect
hidden
mask
masksToBounds
opacity
position
shadowColor
shadowOffset
shadowOpacity
shadowRadius
- 应用实例:
(1)旋转
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sync"]]; imageView.frame = CGRectMake(0, 0, 100, 100); imageView.center = self.view.center; [self.view addSubview:imageView]; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; //设置动画时间 animation.duration = 1; //起点 animation.fromValue = @(0); //终点 animation.toValue = @(2*M_PI); //重复次数,一直重复 animation.repeatCount = MAXFLOAT; //添加动画 [imageView.layer addAnimation:animation forKey:nil]; //当图片加载完后,直接移除动画
(2)摇一摇
- [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES; //摇动手势
- (void)viewDidLoad { [super viewDidLoad]; //启动摇一摇 [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES; } - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { NSLog(@"摇一摇开始"); CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"]; animation.duration = 0.5; //原路返回,这样就只用设置去程 animation.autoreverses = YES; //translation相对原来的位移偏移量 animation.toValue = @(-50); [self.topImageView.layer addAnimation:animation forKey:nil]; animation.toValue = @(50); [self.bottomImageView.layer addAnimation:animation forKey:nil]; }
(3)其他:背景色和圆角
CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, 0, 100, 100); layer.position = self.view.center; layer.backgroundColor = [UIColor redColor].CGColor; [self.view.layer addSublayer:layer]; //背景颜色的动画 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; animation.duration = 3; //这里强制转换 animation.toValue = (id)[UIColor greenColor].CGColor; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; animation.autoreverses = YES; animation.repeatCount = MAXFLOAT; [layer addAnimation:animation forKey:nil]; //圆角半径 animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; animation.duration = 3; animation.toValue = @(50); animation.autoreverses = YES; animation.repeatCount = MAXFLOAT; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; [layer addAnimation:animation forKey:nil];
4.CAAnimationGroup动画组
- 用于把类似的动画放在一组,方便管理。比如上面这个例子,就可以用动画组来创建。
CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, 0, 100, 100); layer.position = self.view.center; layer.backgroundColor = [UIColor redColor].CGColor; [self.view.layer addSublayer:layer]; //背景颜色的动画 CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; animation1.toValue = (id)[UIColor greenColor].CGColor; //圆角半径 CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; animation2.toValue = @(50); CAAnimationGroup *group = [CAAnimationGroup animation]; //管理动画,数组的里面的动画是同时执行 group.animations = @[animation1,animation2]; group.duration = 3; group.removedOnCompletion = NO; group.fillMode = kCAFillModeForwards; group.autoreverses = YES; group.repeatCount = MAXFLOAT; //执行 [layer addAnimation:group forKey:nil];
posted on 2016-03-26 00:48 Wilson_CYS 阅读(440) 评论(0) 编辑 收藏 举报