CoreAnimation(核心动画)概述

96
旧饭盆mingzhi_liu
2017.01.17 19:06* 字数 2720

demo 地址

内容

  • 关于图层动画相关框架的介绍
  • CoreAnimation结构及图层动画
  • 简单demo使用

1. CoreGraphics,QuartzCore, CoreAnimation区别

对CoreGraphics,QuartzCore, CoreAnimation 这三个概念傻傻分不清,先梳理一下

CoreGraphics(核心图形)

它是iOS的核心图形库,包含Quartz2D绘图API接口,常用的是point,size,rect等这些图形,都定义在这个框架中,类名以CG开头的都属于CoreGraphics框架,它提供的都是C语言函数接口,是可以在iOS和mac OS 通用的

QuartzCore

Quartz是位于Mac OS X的Drawin核心之上的绘图层,这个框架感觉不是很清晰,但是看头文件可以发现,它就是CoreAnimation,这个框架头文件只包含了CoreAnimation.h

CoreAnimation(核心动画)

  • CoreAnimation翻译过来就是核心动画,一组非常强大的API,用来做动画的,非常的简单,但是效果非常绚丽
  • CoreAnimation是跨平台的,既可以支持IOS,也支持MAC OS
  • CoreAnimation执行动画是在后台,不会阻塞主线程
  • CoreAnimation作用在CALayer,不是UIView

  • CoreGraphics和CoreAnimation的关系

    首先它们都是跨iOS和Mac OS 使用的,这点区别于UIKit,并且CoreAnimation中大量使用到CoreGraphics中的类,因为实现动画要用到图形库中的定西

  • 为什么CA神马神马的,用的时候好多都要“.CGXXXX”呢?

    比如 :
    layer.backgroundColor = [UIColor redColor].CGColor;

    首先,CALayer是定义在QuartzCore框架中的,CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框 架中的,而UIColor和UIImage是定义在UIKit框架中的。

    其次,QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用
    但是UIKit只能在iOS中使用。

    所以,为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef。

框架关系


image
  • 可以看出,CoreGraphics是底层绘制框架,我们实际会用到的也就是CG开头的一些底层绘制函数和变量,这是一个纯C语言框架
  • QuartzCore(包含CoreAnimation)框架,是iOS系统的基本渲染框架,是一个OC语言框架,是一套基于CoreGraphics的OC语言封装,封装出了基本渲染类CALayer

2.CoreAnimation结构及图层动画 官方文档

核心动画类结构


image
  • CALayer 图层类
  • CAAnimation 动画计时类
  • CAAnimationGroup 是个动画组,可以同时进行缩放,旋转
  • CAPropertyAnimation 也是个抽象类,本身不具备动画效果,只有子类才有。
  • CATransition 转场动画,界面之间跳转(切换)
  • CAConstraint 布局约束类
  • CATransaction 事物类,可以同时设置多个layer层的动画效果。可以通过隐式和显式两种方式来进行动画操作

2.1 关于图层

CALayer基本属性
@property CGRect bounds; //宽度和高度
@property CGPoint position; //位置(默认指中点,具体由anchorPoint决定)
@property CGPoint anchorPoint; // 锚点(x,y的范围都是0-1),决定了position的位置
@property CGColorRef backgroundColor; // 背景颜色(CGColorRef类型)
@property CATransform3D transform; //形变属性

可动画属性特点:

* 直接对它付值可产生隐士动画
* CAAnimation的keyPath可以设置为这个属性的名字

对这些属性赋值的时候,layer会让它的delegate调用actionForLayer:forKey:方法获取一个返回值,这个返回值可能是这样几种情况:
1、是一个nil,则layer会走自己的隐式动画;
2、是一个NSNull,则layer不会做任何动画;
3、是一个实现了CAAction协议的对象,则layer会用这个对象生成一个CABasicAnimation加到自己身上执行动画
CALayer与UIView的关系
  • UIView之所以能显示在屏幕上,完全是因为它内部的一个图层:

    在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。

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

    当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后, 系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。

    换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能。

  • 对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
    所以,如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以。当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

总结:CALayer作为一个跨平台框架(OS X和iOS)QuatzCore的类,iOS系统
为了处理用户交互事件(触屏操作)用UIView封装了一次CALayer,UIView本
身负责处理交互事件,其持有一个Layer,用来负责绘制这个View的内容。而
我们对UIView的和绘制相关的属性赋值和访问的时候(frame、
backgroundColor等)UIView实际上是直接调用其Layer对应的属性(frame对
应frame,center对应position等)的getter和setter。
核心动画渲染框架

image
  • 图层树:包含每一层的对象模型值。他们就是你设定的图层的属性值
  • 呈现树:包含了当前动画发生时候将要显示的值(例如你要给图层背景颜色设置新的值的时候,它会立即修改图层树里面相应的值。但是在呈现树里面背景颜色值在将要显示给用户的时候才被更新为新值)
  • 渲染树:在渲染图层的时候使用呈现树的值 (渲染树负责执行独立于应用活动的复杂操作。渲染由一个单独的进程或线程来执行,使其对应用程序的运行循环影响最小)
图层几何属性(mac os 下坐标系)

  • position:属性是一个CGPoint值, 指定图层相当于它父图层的位置, 该值基于父图层的坐标系
  • bounds:属性是CGRect值, 指定图层的大小(bounds.size)和图层的 原点(bounds.origin)
  • anchorPoint:属性是CGPoint值,anchorPoint指定了bounds相对于position的值,同时作为变换的支点,锚点使用单元空间坐标系表示,(0,0)接近图层的原点,(1,1)原点的对角点。(当你设置图层的 frame 属性的时候,position 会根据锚点(anchorPoint)相应的改变,而当你设置图层的 position 属性的候,bounds 会根据锚点(anchorPoint)做相应的改变)
    (锚点就是layer的那一个点在point上)

图层的 frame、bounds、position 和 anchorPoint 关系如下图所示


anchorPoint 默认值为(0.5,0.5),位于图层的中心点。图层的 position 值为(100.0,100.0),bounds 为(0.0,0.0,120,80.0)。通过计算得到图层的 frame为(40.0,60.0,120.0,80.0)

几种常用的Layer
  • CAEmitterLayer

    CAEmitterLayer是CoreAnimation框架中的粒子发射层,博客中有详细的介绍和范例,这里不再重复,地址如下:粒子效果的应用和火焰范例

  • CAGradientLayer

    CAGradientLayer是用于色彩梯度展示的layer图层,通过CAGradientLayer,我们可以很轻松的创建出有过渡效果的色彩图

  • CAReplicatorLayer

    CAReplocatorLayer是拷贝视图容器,我们可以通过它,将其中的子layer进行拷贝,并进行一些差异处理

  • CAShapeLayer

    CAShapeLayer是图形layer层,我们可以自定义这个层的形状

  • CATextLayer

    CATextLayer可以进行文本的绘制

2.2 关于动画

UIViewAnimation动画

iOS开发中,UIKit为我们封装好的核心动画层的方法,通过这些方法,基本能达到我们项目的大多需求,其中UIView动画使用简便,开发中应用十分广泛

  • UIView动画执行的两种方式
  1. 使用begin和commit方式

    例如:
    UIView * view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
    [self.view addSubview:view];
    view.backgroundColor=[UIColor redColor];
    [UIView beginAnimations:@"test" context:nil];
    [UIView setAnimationDuration:3];
    view.backgroundColor=[UIColor orangeColor];
    [UIView commitAnimations];//执行commit后,动画即开始执行
  2. 使用block块api

    例如:
    [UIView animateWithDuration:1 animations:^{
      _myView.alpha=0;
    } completion:^(BOOL finished) {
      if (finished) {
          _myView.alpha=1;
      }
    }];

    支持动画的属性


image
CAAnimation

如果你想更加自由的通过动画操作视图的属性,你就需要跳过UIKit的封装,使用CoreAnimation核心动画层的方法来实现动画,CoreAnimation能够实现更多复杂、好看、高效的动画效果

* 阴影,圆角,带颜色的边框。
* 3D变化。
* 透明遮罩
* 多级非线性动画

CAAnimation是CoreAnimation框架中执行动画的基类,是个抽象类,不具备动画效果,必须用它的子类才有动画效果,是所有动画对象的父类,负责控制动画的持续时间和速度

  • 隐式动画:不指定任何动画类型,仅改变非根层layer(手动创建的layer)动画属性,coreAnimation会决定如何何时去做动画,你不用做额外操作
  • 显式动画:需要创建一个动画对象,并设置开始和结束值,直到把动画应用到某图层上,动画才开始执行

CAAnimation相关的几个动画类的关系图


image
CAPropertyAnimation

是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation

  • @property(nullable, copy) NSString *keyPath;

通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果

CABasicAnimation

基本动画,通过设定起始点,终点,时间,动画会沿着你这设定点进行移动,
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。

CAKeyframeAnimation

主要操作属性有keyPath和values值组合,以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
与CABasicAnimation的区别是:

  • CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
  • CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation
CAAnimationGroup

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

CATransition

用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点。

UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果。

使用CoreAnimation做动画的时候,遵循四步就好
1.创建CAAnmation子对象
2.设置CAAnmation的属性
3.调用CALayer的addAnimation:forKey将CAAnimation对象添加到CALayer上,就能执行动画
4.调用CALayer的removeAnimationForKey方法可以停止CALayer中的动画

遗留问题

  1. 隐式动画,显式动画和隐式事务,显示事务混淆
  2. 没有用到CATransaction begin,commit 依然有动画效果

概念补充

显式动画&隐式动画
  • CALayer的动画分为隐式动画和显式动画,UIView内部关联了一个CALayer,叫它“Root CALayer”.
  • 所有的非Root CALayer的“Animatable”属性在修改的时候会默认的产生隐式动画
CATransaction 事务

CATransaction 是核心动画里负责协调多个动画更新显示操作,保证多个动画同时进行,用于配置隐式动画,即CALayer属性修改依赖CATransaction.

和动画类似CATransaction也分为隐式事务和显式事务

隐式事务:在某次RunLoop中设置了一个“Animatable”属性,如果当前没有设置事务,则会自动创建一个CATransaction,并在当前线程的下一个RunLoop中commit这个CATransaction

显式事务:直接调用CATransaction的[CATransaction begin],[CATransaction commit]等相关方法

另外事务可以嵌套,当事务嵌套时候,只有最外层的事务commit了之后,整个动画才会执行。

参考资料

几种常用Layer的使用解析

贝塞尔曲线原理(简单阐述)

日记本