目  录:

一、Core Animation开发步骤

二、Core Animation的继承结构

三、CAAnimation常用的属性

四、CAPropertyAnimation(属性动画)

五、CABasicAnimation(基本动画)

六、CAKeyframeAnimation(关键帧动画)

七、CAAnimationGroup(动画组)

八、CATransition(转场动画)

  上节中分享了核心动画的基础部分CALayer,知道了核心动画的操作对象不是UIView,而是基于CALayer。今天来看下Core Animation如何实现动画效果的。

Core Animation是一组非常强大的动画处理API,使用它能我们可以做出非常炫丽的动画效果,而且往往是事半功倍!不过在iOS 7之前使用它需要先添加QuartzCore.framework和引入对应的框架<QuartzCore/QuartzCore.h>。Core Aaimation在创建动画上不仅简单,而且具有更好的性能,原因有两个:
(1)动画在单独的线程中完成,不会阻塞主线程。
(2)动画只会重绘界面上变化的部分(部分刷新)。
一、Core Animation开发步骤
Core Animation开发步骤,大致划分两步:
1.初始化一个动画对象(CAAnimation)并设置一些动画相关属性
(1)CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties)
2.添加动画对象到层(CALayer)中,开始执行动画
(1)通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就能触发动画了。通过调用removeAnimationForKey可以停止层中的动画。
(2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
二、Core Animation的继承结构
Core Animation动画的核心时CALayer,每个UIView都有自己的CALayer,而且每个CALayer都可不断地添加子CALayer,CALayer所在的CALayer称为父CALyaer,CALayer的这种组织方式被称为Layer Tree(各Layer之间的机构就像一棵树)。
图为:CAAnimation继承结构

  

  注意:图中的黑色虚线代表“继承”某个类,红色虚线代表“遵守”某个协议。

  从上图可以看出CAAnimation时所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,如果设置动画应该使用它具体的子类。

  (1)CAAnimation:它是所有动画类的基类,它实现了CAMediaTiming协议,提供了动画的持续时间、速度和重复计数等。CAAnimation还实现了CAAction协议,该协议为CALayer动画触发的动作提供标准化响应。

  (2)CATransition:可以通过预置的过渡效果来控制CALayer层的过渡动画。

  (3)CAPropertyAnimation:它代表一个属性动画,可通过+animationWithKeyPath:类方法来创建属性动画实例(程序一般创建该子类的实例),该方法需要指定一个CALayer支持动画的属性,然后通过它的子类控制CALayer的动画属性慢慢睇改变,即可实现CALayer动画。

  (4)CBasicAnimation:简单地控制CALayer层的属性慢慢改变,从而实现动画效果。很多CALayer层的属性值的修改默认会执行这个动画类。比如大小、透明度、颜色等属性。

  (5)CAKeyframeAnimation:支持关键帧的属性动画,该动画的最大特点在于可通过values属性指定多个关键帧,通过多个关键帧可以指定动画的各阶段的关键值。

  (6)CAAnimationGroup:用于将多个动画组合在一起执行。

三、CAAnimation常用的属性(红色代表来自CAMediaTiming协议的属性)。

  (1) duration:动画的持续时间

  (2) repeatCount:重复的次数,无线循环可以设置HUGE_VALF或者MAXFLOAT

  (3)repeatDuration:重复时间

  (4)removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards(产生一个动画将CALayer移动到另外一个位置,而CALayer的实际位置却没有改变,仍然在动画开启前的位置)

(5)beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

默认值为0,无延迟

(6)delegate:动画代理
(7) fillMode:动画填充模式(要想fillMode有效,需要设置removedOnCompletion = NO),它的属性值是一个枚举类型的,如下:
–kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态

–kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
–kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
–kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态

(8)速度控制函数(CAMediaTimingFunction)

–kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
–kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
–kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
–kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
 四、CAPropertyAnimation(属性动画)

是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:
(1)CABasicAnimation(基本动画)
(2)CAKeyframeAnimation(关键帧动画)
属性说明:
–keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@“position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果。
五、CABasicAnimation(基本动画)
CABasicAnimation有两个属性:

–fromValue:keyPath相应属性的初始值(起始点)
–toValue:keyPath相应属性的结束值(结束点)
动画过程说明:

–随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。
–keyPath内容是CALayer的可动画Animatable属性
–如果fillMode=kCAFillModeForwards同时removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
案例分析:
#import "ViewController.h"@interface ViewController ()
@property(strong,nonatomic)CALayer *subLayer;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//创建子层self.subLayer = [CALayer layer];self.subLayer.bounds = CGRectMake(0, 0, 100, 100);self.subLayer.position = CGPointMake(100, 100);self.subLayer.cornerRadius = 50;self.subLayer.backgroundColor = [[UIColor greenColor]CGColor];[self.view.layer addSublayer:self.subLayer];UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];tap.numberOfTapsRequired = 1;//接受几个手指响应的事件tap.numberOfTouchesRequired = 1;[self.view addGestureRecognizer:tap];}
-(void)tap:(UITapGestureRecognizer *)sender
{CGPoint location = [sender locationInView:self.view];CABasicAnimation *basic = [[CABasicAnimation alloc]init];basic.duration = 3.0;//动画时长basic.keyPath = @"position";basic.removedOnCompletion = NO;basic.fillMode = kCAFillModeForwards;basic.delegate = self;//将动画的结束位置移动到点击的坐标处basic.toValue = [NSValue valueWithCGPoint:location];[self.subLayer addAnimation:basic forKey:@"basic"];}
- (IBAction)pauseClicked:(UIButton *)sender
{if (sender.tag == 0){//动画暂停[self animationPause];sender.tag = 1;}else{//动画恢复[self animationResume];sender.tag = 0;}
}
//动画暂停
-(void)animationPause
{//获取当前暂停的时间段CFTimeInterval pauseTime = [self.subLayer convertTime:CACurrentMediaTime() fromLayer:nil];NSLog(@"pausetTime:%f",pauseTime);//将速度降为0,动画停止self.subLayer.speed = 0.0;//保存暂停时间self.subLayer.timeOffset = pauseTime;
}
-(void)animationResume
{CFTimeInterval pauseTime = self.subLayer.timeOffset;self.subLayer.timeOffset = pauseTime;self.subLayer.speed = 1.0;self.subLayer.beginTime = 0.0;//计算开始时间CFTimeInterval beginTime = [self.subLayer convertTime:CACurrentMediaTime() fromLayer:nil]-pauseTime;self.subLayer.beginTime = beginTime;
//    NSLog(@"beginTime:%@",beginTime);}
#pragma mark - 动画代理的方法
//动画开始
-(void)animationDidStart:(CAAnimation *)anim
{NSLog(@"animationDidStart");
}
//动画结束
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{//NSLog(@"%@",((CABasicAnimation *)anim).toValue);NSValue *toValue = ((CABasicAnimation *)anim).toValue;CGPoint location = [toValue CGPointValue];self.subLayer.position = location;
}@end

六、CAKeyframeAnimation(关键帧动画)

  关键帧动画也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值

  属性说明:

  - values:上述的NSArray对象。里面的元素称为“帧”。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧。

  - path:可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和positon起作用。如果设置了path,那么values将被忽略

  - keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的。

#import "ViewController.h"
#define MAX_TOUCH_NUM 5//最大点击次数
@interface ViewController ()
@property(strong,nonatomic)NSMutableArray *points;
@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 = self.view.center;self.drawLayer.backgroundColor = [[UIColor whiteColor]CGColor];[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 greenColor]CGColor];[self.view.layer addSublayer:self.subLayer];self.points = [NSMutableArray array];
//    //设置跟layer的代理self.drawLayer.delegate = self;}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self.view];//创建路径self.path = CGPathCreateMutable();CGPathMoveToPoint(self.path, nil, location.x, location.y);}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{//将当前点加到路径中去UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self.view];CGPathAddLineToPoint(self.path,nil, location.x, location.y);[self.drawLayer setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{//创建帧动画(路径动画)CAKeyframeAnimation *keyFrame = [[CAKeyframeAnimation alloc]init];keyFrame.keyPath = @"position";keyFrame.path = self.path;keyFrame.duration = 3.0f;//设置动画保存在最后的位置keyFrame.removedOnCompletion = NO;keyFrame.fillMode = kCAFillModeForwards;keyFrame.delegate = self;[self.subLayer addAnimation:keyFrame forKey:@"keyFrame"];}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{CGPathRelease(self.path);
}
#pragma mark - 层绘制的代理方法
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{CGContextAddPath(ctx, self.path);CGContextSetStrokeColorWithColor(ctx, [[UIColor blueColor]CGColor]);CGContextDrawPath(ctx, kCGPathStroke);}
@end

  运行效果图,如下:  

 七、CAAnimationGroup动画组

  动画组是CAAnimation子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中的所有动画可以同时并发运行。

  属性说明:

  - animations:用来管理多个动画对象的NSArray。默认情况下,多个动画是同时执行的,可以通过设置动画对象的beginTime来改变动画的开始执行时间。

  案例分析:

#import "ViewController.h"@interface ViewController ()
@property(strong,nonatomic)CALayer *subLayer;@end@implementation ViewController- (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 blueColor]CGColor];[self.view.layer addSublayer:self.subLayer];UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];tap.numberOfTapsRequired = 1;tap.numberOfTouchesRequired = 1;[self.view addGestureRecognizer:tap];
}
//创建旋转动画
-(CABasicAnimation *)rotationAnimationFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue
{//创建基本动画CABasicAnimation *animationRotation = [[CABasicAnimation alloc]init];animationRotation.keyPath = @"transform.rotation.z";animationRotation.fromValue = @(fromValue);animationRotation.toValue = @(toValue);animationRotation.duration = 1.0f;animationRotation.removedOnCompletion = NO;animationRotation.fillMode = kCAFillModeForwards;return animationRotation;}
//创建缩放动画
-(CABasicAnimation *)scaleAnimationFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue
{CABasicAnimation *scaleAnimation = [[CABasicAnimation alloc]init];scaleAnimation.keyPath = @"transform.scale";scaleAnimation.fromValue = @(fromValue);scaleAnimation.toValue = @(toValue);scaleAnimation.duration = 2.0f;scaleAnimation.removedOnCompletion = NO;scaleAnimation.fillMode = kCAFillModeForwards;return scaleAnimation;}
-(void)tap:(UITapGestureRecognizer *)sender
{//创建动画组CAAnimationGroup *group = [[CAAnimationGroup alloc]init];NSArray *animations = @[[self rotationAnimationFromValue:-M_PI toValue:-M_PI_4],                        [self scaleAnimationFromValue:1.0 toValue:2.0]];group.animations = animations;//动画组中的动画的属性,受动画组的控制(比如:动画内设置了大小,时长,在动画组内不起作用,以动画组设置为准)group.duration = 4.0f;
//        group.removedOnCompletion = NO;
//        group.fillMode = kCAFillModeForwards;//延时执行
//    group.beginTime = CACurrentMediaTime()+1.0f;[self.subLayer addAnimation:group forKey:@"animation"];}
@end

八、CATransition转场动画

  CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS 比Mac OSX的转场动画效果少一点。

UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果。
动画属性:
–type:动画过渡类型
–subtype:动画过渡方向
–startProgress:动画起点(在整体动画的百分比)
–endProgress:动画终点(在整体动画的百分比)
#import "ViewController.h"@interface ViewController ()
@property(strong,nonatomic)UIImageView *imageView;
@property(assign,nonatomic)NSInteger index;@end@implementation ViewController- (void)viewDidLoad
{[super viewDidLoad];self.index = 0;//创建imageView;self.imageView = [[UIImageView alloc]initWithFrame:self.view.frame];self.imageView.contentMode = UIViewContentModeScaleAspectFit;self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",self.index]];self.imageView.userInteractionEnabled = YES;[self.view addSubview:self.imageView];UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;[self.imageView addGestureRecognizer:leftSwipe];UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;[self.imageView addGestureRecognizer:rightSwipe];
}
-(void)leftSwipe:(UISwipeGestureRecognizer *)sender
{if (sender.direction == UISwipeGestureRecognizerDirectionLeft){if (self.index > 0){self.index--;}}else{if (self.index < 9){self.index++;}}//过场动画CATransition *transition = [[CATransition alloc]init];//动画类型transition.type = @"cube";//设置方向transition.subtype = kCATransitionFromBottom;//设置时长transition.duration = 0.5f;//添加动画[self.imageView.layer addAnimation:transition forKey:@"transition"];self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",self.index]];
}@end

  到此,核心动画就完结了。

iOS_核心动画(二)相关推荐

  1. iOS动画专题·UIView二维形变动画与CAAnimation核心动画

    点击上方"iOS开发",选择"置顶公众号" 关键时刻,第一时间送达! 1. iOS动画 总的来说,从涉及类的形式来看,iOS动画有:基于UIView的仿射形变动 ...

  2. iOS 动画专题(UIView二维形变动画与CAAnimation核心动画)

    文章目录 1. iOS动画 2. UIView动画 2.1 设置UIView动画的两种语法形式 2.2 设置属性形变动画的两种类型 2.3 与动画相关的属性 2.3.1 UIView与动画相关的属性- ...

  3. iOS之CALayer与核心动画(二)

    01-转盘 1.搭建界面把转盘View给封装起来. 由于界面是固定不变的,可以弄一个Xib展示界面.外界使用时直接来一个类方法直接调用. 2.让转盘进行旋转.在封装的View内部提供一个开始旋转的方法 ...

  4. iOS学习——核心动画之Layer基础

    iOS学习--核心动画之Layer基础 1.CALayer是什么? CALayer我们又称它叫做层.在每个UIView内部都有一个layer这样一个属性,UIView之所以能够显示,就是因为它里面有这 ...

  5. iOS开发UI篇—核心动画简介

    一.简单介绍 Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. ...

  6. 猫猫学IOS(四十)UI之核心动画_抖动效果_CAKeyframeAnimation

    猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 效果: 效果一: 效果二: ...

  7. iOS开发CoreAnimation解读之一——初识CoreAnimation核心动画编程

    iOS开发CoreAnimation解读之一--初识CoreAnimation核心动画编程 一.引言 二.初识CoreAnimation 三.锚点对几何属性的影响 四.Layer与View之间的关系 ...

  8. iOS核心动画之CoreAnimation

    本文目录 一.Core Animation简介 二.Core Animation的使用步骤 三.CAAnimation 四.CAPropertyAnimation 回到顶部 一.Core Animat ...

  9. iOS开发UI篇—核心动画(基础动画)

    一.简单介绍 CAPropertyAnimation的子类 属性解析: fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 随着动画的进行,在长度为du ...

最新文章

  1. ssm多数据源的操作
  2. linux中matlab,linux中Matlab编译m文件
  3. 美工一流的个人网站源码系列(2),不漂亮你可以不下载!
  4. csv->Flink SQL->Clickhouse(纯DDL形式)
  5. DateOnly和TimeOnly类型居然不能序列化!!! .Net 6下实现自定义JSON序列化
  6. 对qps、tps、pv、uv的理解
  7. 大工14秋《计算机应用基础》在线测试2,2017大工《计算机应用基础》在线测试2答案.doc...
  8. linux 脚本 变量为空,Shell判断一个变量是否为空
  9. failed to introspect Class[org.springframework.cloud.context.properties.ConfigurationPropertiesBea]
  10. JS进阶篇--JS数组reduce()方法详解及高级技巧 1
  11. 亟需为个人信息安全“保驾护航”
  12. Python写视图界面--pyqt的使用
  13. 一般处理程序在VS2012中打开问题
  14. 微商分销代理新零售商城源码
  15. 基于FCOS的航拍巡检图像绝缘子识别
  16. MFC仿QQ好友列表控件
  17. ElasticSearch深入浅出
  18. EPLAN小知识——如何在菲尼克斯(PHEONIX)官网下载EPLAN部件
  19. 非2的幂,离散傅里叶变化DFT的快速实现
  20. redis如何设置定时过期_redis设置过期时间

热门文章

  1. mac——清理磁盘空间
  2. 网络安全法及个人信息法律解读
  3. 一次精彩的皮卡车降噪试验过程
  4. python 爬取壁纸网站并保存图片到本地
  5. Aria2-不限速全平台下载利器
  6. Android App包瘦身优化
  7. 《App Store 审查指南》更新,这几条影响不小
  8. 2021年淘宝双11超级红包规则介绍
  9. c++三种排序学习图文笔记(冒泡,插入,快速)
  10. 最优化之凸集、凸函数、上确界、Jensen不等式、共轭函数、Fenchel不等式、拉格朗日乘子法、KKT条件