iOS-核心动画

核心动画(Core Animation)

一、Core animation简单介绍

1.Core Animation,中文翻译为核心动画,是一套包含图形绘制,投影,动画的Objective–C类集合。它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。Core Animation自身并不是一个绘图系统。它只是一个负责在硬件上合成和操纵应用内容的基础构件

2.Core Animation是跨平台的,可以用在Mac OS X和iOS平台。

3.Core Animation负责所有的滚动、旋转、缩小和放大以及所有的iOS动画效果。其中UIKit类通常都有animated:参数部分,它可以允许是否使用动画。

4.Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。不阻塞主线程,可以理解为在执行动画的时候还能点击(按钮)。

用图形处理硬件操纵位图(calayer)要比图形处理软件(uiview)能获得更好的动画效果。

因为操纵的是静态的位图,基于图层的绘图和基于视图的绘图在技术上有明显的不同。

对基于视图的绘图,对视图的改变经常会触发调用视图的drawRect:方法以重绘视图内容。
但是此种方式的代价相对较高,因为它是CPU在主线程上的操作。

对图层的绘图
Core Animation通过尽可能的使用图形硬件操纵缓存后的位图来避免了这种开销,从而完成相同或相似的效果。

5.Core Animation还与Quartz紧密结合在一起,每个UIView都关联到一个CALayer对象,CALayer是Core Animation中的图层。要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

见图解-01-iOS图形层关系

二、Core animation类

核心动画类有以下分类:
1.提供显示内容的图层类。CALayer(下面会着重介绍)
2.动画和计时类。(Animation and Timing Classes)
3.布局和约束类。(CAConstraint)
4.事务类,在原子更新的时候组合图层类。核心动画的基础类包含在 Quartz 核心框架(Quartz Core framework)里面,虽然它的其他图层类在其他框架里面定义。(CATransaction)

详细说明:
2.1 图层类(Layer Classes)
Layer Classes是core animation的基础。Layer Classes提供了一个抽象的概念,这个概念对于那些使用NSview和UIview的开发者来说是很熟悉的。基础层是由CAlayer类提供的,CAlayer是所有Core Animation层的父类。

2.2 动画和计时类(Animation and Timing Classes)     

图层的很多可视化属性是可以隐式动画的。通过简单的改变图层的可动画显示的属性,可以让图层现有属性从当前值动画渐变到新的属性值。例如设置图层的 hidden 属性为 YES 将会触发动画使层逐渐淡出。

2.3 布局管理器类

Application Kit 的视图类相对于 superlayer 提供了经典的“struts and springs”定位 模型。图层类兼容这个模型,同时 Mac OS X 上面的核心动画提供了一套更加灵活 的布局管理机制,它允许开发者自己修改布局管理器。核心动画的 CAConstraint 类 是一个布局管理器,它可以指定子图层类限制于你指定的约束集合。每个约束 (CAConstraint 类的实例封装)描述层的几何属性(左,右,顶部或底部的边缘或水 平或垂直中心)的关系,关系到其同级之一的几何属性层或 superlayer。通用的布局管理器和约束性布局管理器将会在“布局核心动画的图层”部分讨论。

 2.4 事务管理类     

图层的动画属性的每一个修改必然是事务的一个部分。CATransaction 是核心动画里面负责协调多个动画原子更新显示操作。事务支持嵌套使用。

见图解-02-核心动画的类层次结构

着重了解前两个

三、CALayer简介
Core Animation创建动画时候会修改CALayer属性,然后让这些属性流畅地变化。Core Animation相关知识点:图层,图层是动画发生的地方,CALayer总是与UIView关联,通过layer属性访问。CAlayer是所有Core Animation层的父类。

1.CALayer是什么

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。
其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层

@property(nonatomic,readonly,retain) CALayer *layer;

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。
换句话说,UIView本身不具备显示的功能,拥有显示功能的是它内部的图层。

UIView之所以能够显示,完全是因为内部的CALayer对象。因此,通过操作这个CALayer对象,可以很方便地调整UIView的一些界面属性,比如:阴影、圆角大小、边框宽度和颜色等。

CALayer是个与UIView很类似的概念,同样有layer,sublayer...,同样有backgroundColor、frame等相似的属性,我们可以将UIView看做一种特殊的CALayer,只不过UIView可以响应事件而已。
一般来说,layer可以有两种用途,二者不互相冲突:一是对view相关属性的设置,包括圆角、阴影、边框等参数;二是实现对view的动画操控。因此对一个view进行core animation动画,本质上是对该view的.layer进行动画操纵。

2.为什么说 CALayer 很重要

(1). 每个UIView 都有 CALayer,即 UIView.layer,同时 UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它,所以,CALayer 应用很广泛

(2). CALayer 能够对 UIView 做许多设定,如:阴影、边框、圆角和透明效果等,且这些设定都是很有用的

3.CAlayer层的属性

(1)、position和anchorPoint
CALayer有2个非常重要的属性:position和anchorPoint
@property CGPoint position;
用来设置CALayer在父层中的位置
以父层的左上角为原点(0, 0)

@property CGPoint anchorPoint;
称为“定位点”、“锚点”
决定着CALayer身上的哪个点会在position属性所指的位置
以自己的左上角为原点(0, 0)
它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

(2)、隐式动画
每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)
所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画

什么是隐式动画?
当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果
而这些属性称为Animatable Properties(可动画属性)

列举几个常见的Animatable Properties:
bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
position:用于设置CALayer的位置。修改这个属性会产生平移动画

四、CAAnimation(动画类)

CAAnimation是所有动画类的父类,但是它不能直接使用,应该使用它的子类。

见图解-03-CAAnimation类的继承结构图

常见属性有:
duration:动画的持续时间
repeatCount:动画的重复次数
timingFunction:控制动画运行的节奏

类的说明:
(1)能用的动画类只有4个子类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup
1.CABasicAnimation
通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
3.CAAnimationGroup
Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时执行,如何按顺序执行我到时候再讲。
4.CATransition
这个就是苹果帮开发者封装好的一些动画

(2)CAMediaTiming是一个协议(protocol)。
CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
它有个NSString类型的keyPath属性,你可以指定CALayer的某个属性名为keyPath,并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@"position"为keyPath,就会修改CALayer的position属性的值,以达到平移的动画效果

五、Core Animation的使用步骤

1.使用它需要先添加QuartzCore.framework框架和引入主头文件<QuartzCore/QuartzCore.h>(iOS7不需要)
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

在iOS中,展示动画可以类比于显示生活中的“拍电影”。拍电影有三大要素:演员+剧本+开拍,概念类比如下:
演员--->CALayer,规定电影的主角是谁
剧本--->CAAnimation,规定电影该怎么演,怎么走,怎么变换
开拍--->AddAnimation,开始执行

详见代码。。。。。。

六、补充说明
所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
属性解析:
(来自CAMediaTiming协议的属性)
duration:动画的持续时间
repeatCount:动画的重复次数
repeatDuration:动画的重复时间
fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

(非CAMediaTiming协议的属性)
removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
timingFunction:速度控制函数,控制动画运行的节奏
delegate:动画代理

代码用

/*

OC中的动画效果总结
1.视图动画
2.帧动画

1.什么是图层CALayer?
核心动画的所有效果都是基于图层的,没有图层也就没有核心动画效果

2.视图为什么能够显示到屏幕上?

1.调用drawRect方法,如果我们自己绘制了东西,他会显示出来
2.在显示图形之前他会创建一个图层对象(CALayer),然后把需要画的东西都放到图层上,然后呈现给用户看
3.没有图层就没有视图的显示功能,也就是没有图层就没有界面

3.图层能够用来做什么?
使用图层来操作视图的外观属性,这也是学习图层的主要目的
1.阴影效果
2.边框效果
3.圆角效果
4.更强大的动画效果

*/

/*

1.根层
所有的视图,默认情况下都有一个layer层对象,这个层就是根层
通过addSubLayer添加的层都是子层

2.隐式动画都是相对于子层来说的
当修改了某个子层的属性的时候,会默认产生动画效果,就是所谓的隐式动画

3.修改哪些属性会产生隐式动画效果
1.Frame 缩放动画
2.backgroundColor 会产生颜色渐变动画

4.关闭隐式动画
CATransaction 是layer内部设置隐士动画的开关

*/

/*

1.什么是核心动画?
是苹果提供的非常强大的动画处理API,能够做出非常绚丽的动画效果,而且使用的代码量非常少

2.核心动画是直接作用在CALayer上的

3.核心动画的基础功能都定义在CAAnimation中

CAAnimation提供了三个子类:

CAAnimationGroup
CATransaction
CAPropertyAnimation : CABasicAnimation,CAKeyframeAnimation

*/

//此外,动画的暂停与开始可以通过下面的方式做到:
-(IBAction)pause:(id)sender{
    [self pauseLayer:self.layer];
}
-(IBAction)resume:(id)sender{
    [self resumeLayer:self.layer];
}
-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

绕矩形循环跑(拓展)

- (void)initRectLayer
 {
     //新处理一下self.layer
     self.layer.frame = CGRectMake(15, 200, 30, 30);
     self.layer.cornerRadius = 15;
 
     //来个帧动画
     CAKeyframeAnimation *rectRunAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
     //设定关键帧位置,必须含起始与终止位置
     rectRunAnimation.values = @[
                                [NSValue valueWithCGPoint:self.layer.frame.origin],
                                [NSValue valueWithCGPoint:CGPointMake(320 - 15,self.layer.frame.origin.y)],
                                [NSValue valueWithCGPoint:CGPointMake(320 - 15,self.layer.frame.origin.y + 100)],
                                [NSValue valueWithCGPoint:CGPointMake(15, self.layer.frame.origin.y + 100)],
                                [NSValue valueWithCGPoint:self.layer.frame.origin]];
     //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
     rectRunAnimation.keyTimes = @[
                                  [NSNumber numberWithFloat:0.0],
                                  [NSNumber numberWithFloat:0.6],
                                  [NSNumber numberWithFloat:0.7],
                                  [NSNumber numberWithFloat:0.8],
                                  [NSNumber numberWithFloat:1]];
   
     rectRunAnimation.timingFunctions = @[
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
     //重复次数
     rectRunAnimation.repeatCount = 10;
     //动画结束时是否执行逆动画
     rectRunAnimation.autoreverses  = NO;
     //线性运动方式
     rectRunAnimation.calculationMode = kCAAnimationLinear;
     //持续时间
     rectRunAnimation.duration = 4;
     //添加动画
     [self.layer addAnimation:rectRunAnimation forKey:@"rectRunAnimation"];
    
     /**
      CAKeyFrameAnimation的使用中有以下主要的属性需要注意
      (1)values属性
     
      values属性指明整个动画过程中的关键帧点,例如上例中的A-E就是通过values指定的。需要注意的是,起点必须作为values的第一个值。
     
      (2)path属性
     
      作用与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略。例如上述pathAnimation例子
     
      (3)keyTimes属性
     
      该属性是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结合。例如,你可以传入{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.....
     
      (4)timeFunctions属性
     
      用过UIKit层动画的同学应该对这个属性不陌生,这个属性用以指定时间函数,类似于运动的加速度,有以下几种类型。上例子的AB段就是用了淡入淡出效果。记住,这是一个数组,你有几个子路径就应该传入几个元素
     
      1 kCAMediaTimingFunctionLinear//线性
      2 kCAMediaTimingFunctionEaseIn//淡入
      3 kCAMediaTimingFunctionEaseOut//淡出
      4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
      5 kCAMediaTimingFunctionDefault//默认
     
      (5)calculationMode属性
     
      该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似
     
      1 const kCAAnimationLinear//线性,默认
      2 const kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上
      3 const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
      4 const kCAAnimationCubic//平均,同上
      5 const kCAAnimationCubicPaced//平均,同上
     
      */
}

//CAKeyframeAnimation
//CABasicAnimation算是CAKeyFrameAnimation的特殊情况,即不考虑中间变换过程,只考虑起始点与目标点就可以了。而CAKeyFrameAnimation则更复杂一些,允许我们在起点与终点间自定义更多内容来达到我们的实际应用需求,KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等
- (CAAnimation*)pathAnimation
{
    /**
     CAKeyframeAnimation
    
     在画线的时候,方法的内部默认创建一个path。它把路径都放到了path里面去。
     1.创建路径  CGMutablePathRef 调用该方法相当于创建了一个路径,这个路径用来保存绘图信息。
     2.把绘图信息添加到路径里边。
     以前的方法是点的位置添加到ctx(图形上下文信息)中,ctx 默认会在内部创建一个path用来保存绘图信息。
     在图形上下文中有一块存储空间专门用来存储绘图信息,其实这块空间就是CGMutablePathRef。
     3.把路径添加到上下文中。
     */
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path,NULL,50.0,120.0);
    CGPathAddLineToPoint(path, NULL, 300, 488);
    CGPathAddCurveToPoint(path,NULL,50.0,275.0,150.0,275.0,150.0,120.0);
    CGPathAddCurveToPoint(path,NULL,150.0,275.0,250.0,275.0,250.0,120.0);
    CGPathAddCurveToPoint(path,NULL,250.0,275.0,350.0,275.0,350.0,120.0);
    CGPathAddCurveToPoint(path,NULL,350.0,275.0,450.0,275.0,450.0,120.0);
   
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
   
    [animation setPath:path];
    [animation setDuration:3.0];
   
    CFRelease(path);
    //ARC的诞生大大简化了我们针对内存管理的开发工作,但是只支持管理 Objective-C 对象, 不支持 Core Foundation 对象。Core Foundation 对象必须使用CFRetain和CFRelease来进行内存管理
    //http://blog.csdn.net/yiyaaixuexi/article/details/8553659
   
    return animation;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容