501-核心动画
一、Core Animation(核心动画)
1.简介
1)Core Animation:中文翻译为核心动画,它是一组很强大的动画处理的API。可用在Mac OS X和iOS平台
2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程
3)Core Animation是直接作用在CALayer上的,并非是UIView
2.使用步骤
1)使用它需要先添加QuartzCore.framework框架(iOS7以后无需导入框架)
2)引入主头文件<QuartzCore/QuartzCore.h>
3)初始化一个CAAnimation对象,并设置一些动画相关属性
4)通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就开始动画啦
5)通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
3.transform的属性列表(官方文档搜索“transform value key paths”)

二、CAAnimation
1.CAAnimation的几个子类
1)执行动画之前,必须先初始化一个CAAnimation对象,
2)我们在使用中并不是直接使用CAAnimation这个类,而是使用的是它的几个子类

2.CAAnimation的几个重要属性和方法
1)控制动画运行的节奏
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
kCAMediaTimingFunctionLinear // 匀速
kCAMediaTimingFunctionEaseIn // 渐进
kCAMediaTimingFunctionEaseOut // 渐出
kCAMediaTimingFunctionEaseInEaseOut // 渐进渐出
kCAMediaTimingFunctionDefault // 默认
2)动画的持续时间(默认为0,所以动画必须设置该属性)
@property CFTimeInterval duration;
3)动画的重复次数(默认为0,不重复)
@property float repeatCount;
4)协议代理(这个代理无需增收任何协议,协议为NSObject的分类方法)
@property(nullable, strong) id delegate;
1 @interface NSObject (CAAnimationDelegate) 2 3 #pragma mark - 动画开始执行 4 - (void)animationDidStart:(CAAnimation *)anim; 5 6 #pragma mark - 动画执行完毕 7 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag; 8 9 @end
5)保持动画执行后的状态(默认为YES)
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
6)决定当前对象在非active时间段的行为(比如:动画执行前和动画执行后) -- fillMode有效,必须设置removedOnCompletion为NO
@property(copy) NSString *fillMode;
kCAFillModeRemoved 默认值,动画前后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
8)初始化方法
+ (instancetype)animation;
总结:1)以上几个属性和方法Core Animation子类都可以使用。
2)开发中只能使用Core Animation的子类,但是子类CAPropertyAnimation也是不能直接使用,也是使用它的子类:
a.CABasicAnimation
b.CAKeyframeAnimation
c.CATransition
d.CAAnimationGroup
3.暂停和恢复动画
1)暂停动画
1 #pragma mark - 暂停动画 2 - (void)pauseLayer:(CALayer*)layer 3 { 4 // 获取当前动画的时刻 5 CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 6 7 // 让CALayer的时间停止走动 8 layer.speed = 0.0; 9 10 // 让CALayer的时间停留在pausedTime这个时刻 11 layer.timeOffset = pausedTime; 12 }
2)恢复动画
1 #pragma mark 恢复动画 2 -(void)resumeLayer:(CALayer*)layer 3 { 4 // 获取暂停动画的时刻 5 CFTimeInterval pausedTime = layer.timeOffset; 6 7 // 让CALayer的时间继续行走 8 layer.speed = 1.0; 9 10 // 取消上次记录的停留时刻 11 layer.timeOffset = 0.0; 12 13 // 取消上次设置的时间 14 layer.beginTime = 0.0; 15 16 // 计算暂停的时间(这里也可以用CACurrentMediaTime() - pausedTime) 17 CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 18 19 // 设置相对于父坐标系的开始时间(往后退timeSincePause) 20 layer.beginTime = timeSincePause; 21 }
三、CAPropertyAnimation(CAAnimation的子类)
1.简介
1)CApropertyAnimation是CAAnimation的子类,但是开发中也不能直接使用。要想创建动画对象,使用的时它的两个子类:
a.CABasicAnimation
b.CAKeyframeAnimation
2.CAPropertyAnimation的几个属性和方法
1)指定CALayer的属性名
@property(nullable, copy) NSString *keyPath;
2)初始化方法
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
总结:以上属性和方法对于它的两个子类:CABasicAnimation和CAKeyframeAnimation也都是存在的
四、CABasicAnimation(CAPropertyAnimation的子类)
1.简介
1)CABasicAnimation是CAPropertyAnimation的子类,使用它可以实现一些基本的动画效果
2)动画效果:可以让CALayer的属性值从某一个值渐变到另一个值
2.CABasicAnimation的几个属性
1)CALayer的属性动画起始值
@property(nullable, strong) id fromValue;
2)CALayer的属性动画终止值
@property(nullable, strong) id toValue;
3)CALayer的属性动画的累加值
@property(nullable, strong) id byValue;
3.代码示例
1 // ViewController.m文件 2 #import "ViewController.h" 3 #import <QuartzCore/QuartzCore.h> // 导入头文件 4 5 @interface ViewController () 6 7 // 成员属性(待动画的View) 8 @property (nonatomic, strong) UIView *myView; 9 10 @end 11 12 @implementation ViewController 13 14 - (void)viewDidLoad { 15 [super viewDidLoad]; 16 17 // 创建myView 18 _myView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; 19 _myView.backgroundColor = [UIColor redColor]; 20 [self.view addSubview:_myView]; 21 22 UIImageView *imageView = [[UIImageView alloc] initWithFrame:_myView.bounds]; 23 imageView.image = [UIImage imageNamed:@"1.jpg"]; 24 [_myView addSubview:imageView]; 25 } 26 27 #pragma mark - 点击空白处 28 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 29 { 30 // 平移动画 31 // [self translationAnimationOne]; // 方法一 32 // [self translationAnimationTwo]; // 方法二 33 34 // 缩放动画 35 // [self scaleAnimationOne]; // 方法一 36 // [self scaleAnimationTwo]; // 方法二 37 38 // 旋转动画 39 [self rotationAnimation]; 40 } 41 42 #pragma mark - 平移动画 43 // 1.方法一 44 - (void)translationAnimationOne 45 { 46 // 1.创建动画对象 47 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 48 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; 49 50 // 2.动画设置 51 // 动画持续时间 52 basicAnimation.duration = 5; 53 // 动画重复次数 54 basicAnimation.repeatCount = 5; 55 // 动画运行节奏 56 // kCAMediaTimingFunctionLinear // 匀速 57 // kCAMediaTimingFunctionEaseIn // 渐进 58 // kCAMediaTimingFunctionEaseOut // 渐出 59 // kCAMediaTimingFunctionEaseInEaseOut // 渐进渐出 60 // kCAMediaTimingFunctionDefault // 默认 61 basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 62 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 63 basicAnimation.delegate = self; 64 // 保持动画执行后的状态 65 basicAnimation.removedOnCompletion = NO; 66 basicAnimation.fillMode = kCAFillModeForwards; 67 68 // 3.动画设置值 69 // position属性是CGPoint类型,必须包装成NSValue对象类型 70 // anchorPoint默认为中点 71 // 中点从(0, 0)到(300, 300) 72 basicAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; 73 basicAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)]; 74 75 // 4.添加动画对象到图层上 76 // 参数1:动画对象 77 // 参数2:动画名称(标记不同动画,方便移除指定动画) 78 [_myView.layer addAnimation:basicAnimation forKey:@"basicAnimation1"]; 79 } 80 // 2.方法二 81 - (void)translationAnimationTwo 82 { 83 // 1.创建动画对象 84 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 85 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 86 87 // 2.动画设置 88 // 动画持续时间 89 basicAnimation.duration = 30; 90 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 91 basicAnimation.delegate = self; 92 // 保持动画执行后的状态 93 basicAnimation.removedOnCompletion = NO; 94 basicAnimation.fillMode = kCAFillModeForwards; 95 96 // 3.动画设置值 97 // transform:CATransform3DMakeTranslation(tx, ty, tz) 98 // 从动画的View的原始起点开始,X轴右移300,Y轴下移300,Z轴不动 99 basicAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(300, 300, 0)]; 100 101 // 4.添加动画对象到图层上 102 // 参数1:动画对象 103 // 参数2:动画名称(标记不同动画,方便移除指定动画) 104 [_myView.layer addAnimation:basicAnimation forKey:@"basicAnimation2"]; 105 } 106 107 #pragma mark - 缩放动画 108 // 1.方法一 109 - (void)scaleAnimationOne 110 { 111 // 1.创建动画对象 112 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 113 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; 114 115 // 2.动画设置 116 // 动画持续时间 117 basicAnimation.duration = 30; 118 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 119 basicAnimation.delegate = self; 120 // 保持动画执行后的状态 121 basicAnimation.removedOnCompletion = NO; 122 basicAnimation.fillMode = kCAFillModeForwards; 123 124 // 3.动画设置值 125 // 起始200*200缩小到100*100 126 basicAnimation.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)]; 127 basicAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 100, 100)]; 128 129 // 4.添加动画对象到图层上 130 // 参数1:动画对象 131 // 参数2:动画名称(标记不同动画,方便移除指定动画) 132 [_myView.layer addAnimation:basicAnimation forKey:@"basicAnimation3"]; 133 } 134 // 2.方法二 135 - (void)scaleAnimationTwo 136 { 137 // 1.创建动画对象 138 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 139 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 140 141 // 2.动画设置 142 // 动画持续时间 143 basicAnimation.duration = 30; 144 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 145 basicAnimation.delegate = self; 146 // 保持动画执行后的状态 147 basicAnimation.removedOnCompletion = NO; 148 basicAnimation.fillMode = kCAFillModeForwards; 149 150 // 3.动画设置值 151 // 起始动画View:原始View的宽缩小为一半,高缩小为一半,Z轴不变 152 // 结束动画View:原始View的宽扩大为二倍,高扩大为三倍,Z轴不变 153 basicAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 1)]; 154 basicAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2, 3, 1)]; 155 156 // 4.添加动画对象到图层上 157 // 参数1:动画对象 158 // 参数2:动画名称(标记不同动画,方便移除指定动画) 159 [_myView.layer addAnimation:basicAnimation forKey:@"basicAnimation4"]; 160 } 161 162 #pragma mark - 旋转动画 163 - (void)rotationAnimation 164 { 165 // 1.创建动画对象 166 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 167 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 168 169 // 2.动画设置 170 // 动画持续时间 171 basicAnimation.duration = 30; 172 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 173 basicAnimation.delegate = self; 174 // 保持动画执行后的状态 175 basicAnimation.removedOnCompletion = NO; 176 basicAnimation.fillMode = kCAFillModeForwards; 177 178 // 3.动画设置值 179 // 沿着(0, 0, 1)这个向量方向旋转45°角 180 basicAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)]; 181 182 // 4.添加动画对象到图层上 183 // 参数1:动画对象 184 // 参数2:动画名称(标记不同动画,方便移除指定动画) 185 [_myView.layer addAnimation:basicAnimation forKey:@"basicAnimation5"]; 186 } 187 188 #pragma mark - 协议方法<CAAnimationDelegate> 189 // 1.动画开始 190 - (void)animationDidStart:(CAAnimation *)anim 191 { 192 NSLog(@"动画开始"); 193 } 194 // 2.动画结束 195 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 196 { 197 NSLog(@"动画结束"); 198 } 199 200 @end
总结:1)CABasicAnimation只能是从一个值到一个值(两个值之间的切换),有一定的局限性
2)如果将以上代码是咧中属性值toValue换成byValue,就变成了在原有基础上的累计
五、CAKeyframeAnimation(CAPropertyAnimation的子类)
1.简介
1)CAkeyframeAnimation:意思就是“帧动画”,也是CAPropertyAnimation的子类。
2)解决了CABasicAnimation的两个值切换的局限性,可以实现多个值之间的切换
2.CAKeyframeAnimation的几个属性
1)切换值数组
@property(nullable, copy) NSArray *values;
2)动画每一帧的时间(其取值范围为0-1,默认为等分)
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
3)动画行走轨迹
@property(nullable) CGPathRef path;
3.代码示例
1)基本示例
1 // ViewController.m文件 2 #import "ViewController.h" 3 #import <QuartzCore/QuartzCore.h> // 导入头文件 4 5 @interface ViewController () 6 7 // 成员属性(待动画的View) 8 @property (nonatomic, strong) UIView *myView; 9 10 @end 11 12 @implementation ViewController 13 14 - (void)viewDidLoad { 15 [super viewDidLoad]; 16 17 // 创建myView 18 _myView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; 19 _myView.backgroundColor = [UIColor redColor]; 20 [self.view addSubview:_myView]; 21 22 UIImageView *imageView = [[UIImageView alloc] initWithFrame:_myView.bounds]; 23 imageView.image = [UIImage imageNamed:@"1.jpg"]; 24 [_myView addSubview:imageView]; 25 } 26 27 #pragma mark - 点击空白处 28 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 29 { 30 // 平移动画 31 // [self translationAnimation]; 32 33 // 指定轨迹动画 34 [self pathAnimation]; 35 } 36 37 #pragma mark - 平移动画 38 - (void)translationAnimation 39 { 40 // 1.创建动画对象 41 // 初始化方法1:父类(CAPropertyAnimation)的方法 42 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 43 CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 44 // 初始化方法2:父类(CAPropertyAnimation)的父类(CAAnimation)的方法 45 // CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animation]; 46 // keyframeAnimation.keyPath = @"position"; 47 48 // 2.动画设置 49 // 动画持续时间 50 keyframeAnimation.duration = 1.5; 51 // 动画每一帧的时间(默认为平分,取值范围为0-1) 52 // keyframeAnimation.keyTimes = @[@(0.5), @(0.5), @(0.25), @(0.25)]; 53 // 动画运行节奏 54 // kCAMediaTimingFunctionLinear // 匀速 55 // kCAMediaTimingFunctionEaseIn // 渐进 56 // kCAMediaTimingFunctionEaseOut // 渐出 57 // kCAMediaTimingFunctionEaseInEaseOut // 渐进渐出 58 // kCAMediaTimingFunctionDefault // 默认 59 keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 60 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 61 keyframeAnimation.delegate = self; 62 // 保持动画执行后的状态 63 keyframeAnimation.removedOnCompletion = NO; 64 keyframeAnimation.fillMode = kCAFillModeForwards; 65 66 // 3.动画设置值(共4帧) 67 NSValue *value1 = [NSValue valueWithCGPoint:CGPointZero]; 68 NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; 69 NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(20, 30)]; 70 NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(200, 50)]; 71 NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(150, 300)]; 72 keyframeAnimation.values = @[value1, value2, value3, value4, value5]; 73 74 // 4.添加动画对象到图层上 75 // 参数1:动画对象 76 // 参数2:动画名称(标记不同动画,方便移除指定动画) 77 [_myView.layer addAnimation:keyframeAnimation forKey:@"keyframeAnimation1"]; 78 } 79 80 #pragma mark - 指定轨迹动画 81 - (void)pathAnimation 82 { 83 // 1.创建动画对象 84 // 初始化方法1:父类(CAPropertyAnimation)的方法 85 // 参数:keyPath 字符串类型 需要进行动画改变的CALayer属性 86 CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 87 // 初始化方法2:父类(CAPropertyAnimation)的父类(CAAnimation)的方法 88 // CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animation]; 89 // keyframeAnimation.keyPath = @"position"; 90 91 // 2.动画设置 92 // 动画持续时间 93 keyframeAnimation.duration = 1.0; 94 // 动画每一帧的时间(默认为平分,取值范围为0-1) 95 // keyframeAnimation.keyTimes = @[@(0.2), @(0.1), @(0.5), @(0.2)]; 96 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 97 keyframeAnimation.delegate = self; 98 // 保持动画执行后的状态 99 keyframeAnimation.removedOnCompletion = NO; 100 keyframeAnimation.fillMode = kCAFillModeForwards; 101 102 // 3.动画设置值 103 CGMutablePathRef path = CGPathCreateMutable(); 104 CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 100, 100)); 105 keyframeAnimation.path = path; 106 CGPathRelease(path); // CG类型Create出来的必须释放 107 108 // 4.添加动画对象到图层上 109 // 参数1:动画对象 110 // 参数2:动画名称(标记不同动画,方便移除指定动画) 111 [_myView.layer addAnimation:keyframeAnimation forKey:@"keyframeAnimation2"]; 112 } 113 114 #pragma mark - 协议方法<CAAnimationDelegate> 115 // 1.动画开始 116 - (void)animationDidStart:(CAAnimation *)anim 117 { 118 NSLog(@"动画开始"); 119 } 120 // 2.动画结束 121 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 122 { 123 NSLog(@"动画结束"); 124 } 125 126 @end
2)图标抖动
1 // ViewController.m文件 2 #import "ViewController.h" 3 #import <QuartzCore/QuartzCore.h> // 导入头文件 4 5 @interface ViewController () 6 7 // 成员属性(待动画的View) 8 @property (nonatomic, strong) UIView *myView; 9 @property (nonatomic, strong) UIImageView *imageView; 10 11 @end 12 13 @implementation ViewController 14 15 - (void)viewDidLoad { 16 [super viewDidLoad]; 17 18 // 创建myView 19 _myView = [[UIView alloc] init]; 20 _myView.bounds = CGRectMake(0, 0, 90, 90); 21 _myView.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0); 22 _myView.layer.cornerRadius = 10; 23 [self.view addSubview:_myView]; 24 25 // 创建imageView 26 _imageView = [[UIImageView alloc] initWithFrame:_myView.bounds]; 27 _imageView.image = [UIImage imageNamed:@"1.jpg"]; 28 _imageView.layer.cornerRadius = 10; 29 _imageView.layer.masksToBounds = YES; 30 _imageView.userInteractionEnabled = YES; // 打开交互 31 [_myView addSubview:_imageView]; 32 33 // 添加长按手势 34 UILongPressGestureRecognizer *tap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)]; 35 tap.minimumPressDuration = 1; 36 [_imageView addGestureRecognizer:tap]; 37 } 38 39 #pragma mark - 长按手势的点击事件 40 - (void)tapClick:(UILongPressGestureRecognizer *)tap 41 { 42 // 添加一个删除的按钮 43 UIButton *deleteBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 44 deleteBtn.bounds = CGRectMake(0, 0, 25, 25); 45 deleteBtn.center = CGPointMake(5, 5); 46 deleteBtn.backgroundColor = [UIColor redColor]; 47 deleteBtn.layer.cornerRadius = deleteBtn.bounds.size.width / 2.0; 48 deleteBtn.layer.masksToBounds = YES; 49 deleteBtn.tag = 10; 50 [deleteBtn addTarget:self action:@selector(deleteBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 51 [_myView addSubview:deleteBtn]; 52 53 UIView *lineView = [[UIView alloc] init]; 54 lineView.bounds = CGRectMake(0, 0, deleteBtn.bounds.size.width, 1); 55 lineView.center = CGPointMake(deleteBtn.bounds.size.width / 2.0, deleteBtn.bounds.size.height / 2.0); 56 lineView.backgroundColor = [UIColor whiteColor]; 57 [deleteBtn addSubview:lineView]; 58 59 // 图标抖动 60 [self vibrationAnimation]; 61 } 62 63 #pragma mark - 删除按钮的点击事件 64 - (void)deleteBtnClick:(UIButton *)btn 65 { 66 // 移除动画 67 [_myView.layer removeAnimationForKey:@"keyframeAnimation"]; 68 69 // 删除myView 70 [_myView removeFromSuperview]; 71 } 72 73 #pragma mark - 图标抖动动画 74 - (void)vibrationAnimation 75 { 76 // 1.创建动画对象 77 CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animation]; 78 keyframeAnimation.keyPath = @"transform.rotation"; 79 80 // 2.动画设置 81 // 动画持续时间 82 keyframeAnimation.duration = 0.25; 83 // 动画重复次数 84 keyframeAnimation.repeatCount = 1000; 85 // 动画代理(这个代理不需要遵循任何协议,说明该协议方法只是NSObject的一个分类) 86 keyframeAnimation.delegate = self; 87 // 保持动画执行后的状态 88 keyframeAnimation.removedOnCompletion = NO; 89 keyframeAnimation.fillMode = kCAFillModeForwards; 90 91 // 3.动画设置值 92 CGFloat radian1 = [self radianWithAngle:-5]; 93 CGFloat radian2 = [self radianWithAngle:5]; 94 keyframeAnimation.values = @[@(radian1), @(radian2), @(radian1)]; 95 96 // 4.添加动画对象到图层上 97 // 参数1:动画对象 98 // 参数2:动画名称(标记不同动画,方便移除指定动画) 99 [_myView.layer addAnimation:keyframeAnimation forKey:@"keyframeAnimation"]; 100 } 101 102 #pragma mark - 角度转弧度 103 - (CGFloat)radianWithAngle:(CGFloat)angle 104 { 105 return angle / 180.0 * M_PI; 106 } 107 108 #pragma mark - 协议方法<CAAnimationDelegate> 109 // 1.动画开始 110 - (void)animationDidStart:(CAAnimation *)anim 111 { 112 NSLog(@"动画开始"); 113 } 114 // 2.动画结束 115 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 116 { 117 NSLog(@"动画结束"); 118 } 119 120 @end
六、CATransition(CAAnimation的子类)
1.简介
1)CATransition:意思是“过度动画”,是CAAnimation的子类
2)通常用来做一些切换效果
2.CATransition的几个属性
1)动画过渡类型
@property(copy) NSString *type;

2)动画过渡方向
@property(nullable, copy) NSString *subtype;
// kCATransitionFromRight
// kCATransitionFromLeft
// kCATransitionFromTop
// kCATransitionFromBottom
3)动画翻转起点(百分比,取值为0-1)
@property float startProgress;
4)动画翻转终点(百分比,取值为0-1)
@property float endProgress;
3.代码示例
1 // ViewController.m文件 2 #import "ViewController.h" 3 #import <QuartzCore/QuartzCore.h> // 导入头文件 4 5 // 图片总数 6 #define kImageCount 6 7 8 @interface ViewController () 9 10 // 动画切换的imageView 11 @property (nonatomic, strong) UIImageView *imageView; 12 // 下一张 13 @property (nonatomic, strong) UIButton *frontBtn; 14 // 上一张 15 @property (nonatomic, strong) UIButton *backBtn; 16 // 当前图片的索引 17 @property (nonatomic, assign) int index; 18 19 @end 20 21 @implementation ViewController 22 23 - (void)viewDidLoad 24 { 25 [super viewDidLoad]; 26 27 // 创建imageView 28 _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(30, 40, self.view.bounds.size.width - 30 * 2, self.view.bounds.size.height - 150)]; 29 _imageView.image = [UIImage imageNamed:@"1.jpg"]; 30 _imageView.userInteractionEnabled = YES; // 打开交互 31 [self.view addSubview:_imageView]; 32 33 // 下一张 34 _frontBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 35 _frontBtn.frame = CGRectMake(30, CGRectGetMaxY(_imageView.frame) + 20, _imageView.bounds.size.width / 2.0 - 20, 50); 36 [_frontBtn setTitle:@"下一张" forState:UIControlStateNormal]; 37 _frontBtn.tintColor = [UIColor whiteColor]; 38 _frontBtn.titleLabel.font = [UIFont boldSystemFontOfSize:20]; 39 _frontBtn.backgroundColor = [UIColor redColor]; 40 _frontBtn.layer.cornerRadius = 10; 41 _frontBtn.tag = 10; 42 [_frontBtn addTarget:self action:@selector(frontBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 43 [self.view addSubview:_frontBtn]; 44 45 // 上一张 46 _backBtn = [UIButton buttonWithType:UIButtonTypeSystem]; 47 _backBtn.frame = CGRectMake(CGRectGetMaxX(_frontBtn.frame) + 40, _frontBtn.frame.origin.y, _frontBtn.frame.size.width, _frontBtn.frame.size.height); 48 [_backBtn setTitle:@"上一张" forState:UIControlStateNormal]; 49 _backBtn.tintColor = [UIColor whiteColor]; 50 _backBtn.titleLabel.font = [UIFont boldSystemFontOfSize:20]; 51 _backBtn.backgroundColor = [UIColor redColor]; 52 _backBtn.layer.cornerRadius = 10; 53 _backBtn.tag = 11; 54 [_backBtn addTarget:self action:@selector(backBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 55 [self.view addSubview:_backBtn]; 56 57 // 当前图片索引为1 58 _index = 1; 59 // 当前禁用backBtn 60 _backBtn.enabled = NO; 61 _backBtn.backgroundColor = [UIColor lightGrayColor]; 62 63 64 } 65 66 #pragma mark - 点击事件 67 // 1.下一张 68 - (void)frontBtnClick:(UIButton *)btn 69 { 70 // 当前图片索引+1 71 _index++; 72 73 // 启用backBtn 74 if (_index == 1 + 1) { 75 _backBtn.enabled = YES; 76 _backBtn.backgroundColor = [UIColor redColor]; 77 } 78 79 // 判断是否到最后一张,最后一张禁用frontBtn 80 if (_index == kImageCount) { 81 _frontBtn.enabled = NO; 82 _frontBtn.backgroundColor = [UIColor lightGrayColor]; 83 } 84 85 // 切换图片 86 NSString *imageName = [NSString stringWithFormat:@"%d.jpg", _index]; 87 _imageView.image = [UIImage imageNamed:imageName]; 88 89 // 1.创建转场动画对象 90 CATransition *transition = [CATransition animation]; 91 92 // 2.设置转场动画属性 93 // 动画样式 94 transition.type = @"pageCurl"; 95 // 过渡方向 96 // kCATransitionFromRight 97 // kCATransitionFromLeft 98 // kCATransitionFromTop 99 // kCATransitionFromBottom 100 transition.subtype = kCATransitionFromRight; 101 // 设置翻转起点 102 transition.startProgress = 0.3; 103 // 设置翻转终点 104 transition.endProgress = 0.8; 105 // 动画时间 106 transition.duration = 0.5; 107 // 设置代理 108 transition.delegate = self; 109 110 // 3.添加动画 111 [_imageView.layer addAnimation:transition forKey:@"transition"]; 112 } 113 // 2.上一张 114 - (void)backBtnClick:(UIButton *)btn 115 { 116 // 当前图片索引-1 117 _index--; 118 119 // 启用frontBtn 120 if (_index == kImageCount - 1) { 121 _frontBtn.enabled = YES; 122 _frontBtn.backgroundColor = [UIColor redColor]; 123 } 124 125 // 判断是否第一张,最后一张禁用backBtn 126 if (_index == 1) { 127 _backBtn.enabled = NO; 128 _backBtn.backgroundColor = [UIColor lightGrayColor]; 129 } 130 131 // 切换图片 132 NSString *imageName = [NSString stringWithFormat:@"%d.jpg", _index]; 133 _imageView.image = [UIImage imageNamed:imageName]; 134 135 136 // 1.创建转场动画对象 137 CATransition *transition = [CATransition animation]; 138 139 // 2.设置转场动画属性 140 // 动画样式 141 transition.type = @"pageCurl"; 142 // 过渡方向 143 // kCATransitionFromRight 144 // kCATransitionFromLeft 145 // kCATransitionFromTop 146 // kCATransitionFromBottom 147 transition.subtype = kCATransitionFromLeft; 148 // 设置翻转起点 149 transition.startProgress = 0.3; 150 // 设置翻转终点 151 transition.endProgress = 0.8; 152 // 动画时间 153 transition.duration = 0.5; 154 // 设置代理 155 transition.delegate = self; 156 157 // 3.添加动画 158 [_imageView.layer addAnimation:transition forKey:@"transition"]; 159 } 160 161 #pragma mark - 协议方法<CAAnimationDelegate> 162 // 1.动画开始 163 - (void)animationDidStart:(CAAnimation *)anim 164 { 165 NSLog(@"动画开始"); 166 } 167 // 2.动画结束 168 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 169 { 170 NSLog(@"动画结束"); 171 } 172 173 @end
七、CAAnimationGroup(CAAnimation的子类)
1.简介
1)CAAnimationGroup:意思是“动画组”,是CAAnimation的子类
2)它可以保存一组动画对象。给图层添加CAAnimationGroup后,组中所有动画对象可以同时并发运行
2.CAAnimationGroup的几个属性
1)动画数组
@property(nullable, copy) NSArray<CAAnimation *> *animations;
默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间
3.代码示例
1 // ViewController.m文件 2 #import "ViewController.h" 3 #import <QuartzCore/QuartzCore.h> // 导入头文件 4 5 @interface ViewController () 6 7 // 成员属性 8 @property (nonatomic, strong) UIView *myView; 9 10 @end 11 12 @implementation ViewController 13 14 - (void)viewDidLoad 15 { 16 [super viewDidLoad]; 17 18 // 创建myView 19 _myView = [[UIView alloc] initWithFrame:CGRectMake(30, 100, 200, 200)]; 20 _myView.backgroundColor = [UIColor redColor]; 21 [self.view addSubview:_myView]; 22 } 23 24 #pragma mark - 点击空白处 25 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 26 { 27 // 1.创建动画组里面的动画 28 // 创建旋转动画 29 CABasicAnimation *rotate = [CABasicAnimation animation]; 30 rotate.keyPath = @"transform.rotation"; 31 rotate.toValue = @(M_PI); 32 // 创建缩小动画 33 CABasicAnimation *scale = [CABasicAnimation animation]; 34 scale.keyPath = @"transform.scale"; 35 scale.toValue = @(0.0); 36 // 创建平移动画 37 CABasicAnimation *move = [CABasicAnimation animation]; 38 move.keyPath = @"transform.translation"; 39 move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; 40 41 // 2.创建动画组对象 42 CAAnimationGroup *group = [CAAnimationGroup animation]; 43 44 // 3.将动画添加到动画组 45 // 这里添加不论先后,反正默认是同时并发执行 46 group.animations = @[rotate, scale, move]; 47 48 // 4.设置动画组 49 // 设置动画组的动画时长 50 group.duration = 2.0; 51 // 设置动画组代理 52 group.delegate = self; 53 // 设置动画组动画保留最后状态 54 group.removedOnCompletion = NO; 55 group.fillMode = kCAFillModeForwards; 56 57 // 5.添加动画组到图层 58 [_myView.layer addAnimation:group forKey:@"group"]; 59 } 60 61 #pragma mark - 协议方法<CAAnimationDelegate> 62 // 1.动画开始 63 - (void)animationDidStart:(CAAnimation *)anim 64 { 65 NSLog(@"动画开始"); 66 } 67 // 2.动画结束 68 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 69 { 70 NSLog(@"动画结束"); 71 } 72 73 @end

浙公网安备 33010602011771号