CoreAnimation动画系列

Core Animation 动画的使用步骤

  1. 首先要先有CALayer(因为CoreAnimation是作用在CALayer上的)。
  2. 初始化一个CAAnimation对象,并设置一些动画相关属性。
  3. 通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer中,这样就能开始执行动画了
  4. 通过调用CALayer的removeAnimationForKey:
    方法可以停止CALayer中的动画

1. CALayer详解

CALayer的常用属性

cornerRadius       圆角
shadowColor       阴影颜色
shadowOffset      阴影偏移距离
shadowRadius     阴影模糊程度
shadowOpacity    阴影透明度
borderWidth        描边粗细
borderColor         描边颜色
anchorPoint         锚点
position            位置信息
transfrom           使CALayer产生3D空间的平移、缩放、旋转等变化。

layer的各种属性代码示例:

- (void)viewDidLoad { 
       [super viewDidLoad]; 
        // 设置图片为圆角 (self.qweImageView.frame.size.width / 2 变成圆形)  
        self.imageView.layer.cornerRadius =self.imageView.frame.size.width / 2; 
        // self.imageView.layer.masksToBounds = YES; 
        // 注意:光设置上边一句代码是实现不了效果的(下边的maskToBounds这个属性影响layer层的阴影效果) 
        // 设置layer的阴影颜色
        self.imageView.layer.shadowColor = [UIColor blueColor].CGColor;
         // 设置layer的透明度
        self.imageView.layer.shadowOpacity = 0.5f;
         // 设置阴影偏移量
        self.imageView.layer.shadowOffset = CGSizeMake(-30, 20);
        // 设置阴影的模糊度
        self.imageView.layer.shadowRadius = 1;
        // 创建View19 UIView *myView = [[UIView alloc] init];
        myView.backgroundColor = [UIColor redColor];
        // 设置frame
        myView.frame = CGRectMake(100, 500, 100, 100);
        // 设置视图圆角 (self.qweImageView.frame.size.width / 2 如果是方形视图变成圆形)
        myView.layer.cornerRadius = myView.frame.size.width / 2;
        // 设置阴影颜色
        myView.layer.shadowColor = [UIColor lightGrayColor].CGColor;
       // 设置阴影偏移量
       myView.layer.shadowOffset = CGSizeMake(10, 10);
       // 设置阴影的透明度
       myView.layer.shadowOpacity = 0.8f;
       // 设置阴影的模糊度
       myView.layer.shadowRadius = 1;
       // 添加到View上
        [self.view addSubview:myView];
       [self customLayer];
 }
 - (void)customLayer {
       // 创建一个layer对象
       CALayer *layer = [CALayer layer];
       // 设置对象的位置和大小
       layer.frame = CGRectMake(300, 280, 100, 100);
       // 设置背景颜色
       layer.backgroundColor = [UIColor redColor].CGColor;
       // 设置锚点
       // layer.anchorPoint = CGPointMake(0, 0);
       // 设置大小
       layer.position = CGPointMake(100, 100);
       // layer需要添加到layer层
        [self.view.layer addSublayer:layer];
 }
CALayer上动画的暂停和恢复
  • 暂停
-(void)pauseLayer:(CALayer*)layer { 
      CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
      // 让CALayer的时间停止走动 
      layer.speed = 0.0; 
      // 让CALayer的时间停留在pausedTime这个时刻
      layer.timeOffset = pausedTime; 
}
  • 恢复
-(void)resumeLayer:(CALayer*)layer { 
      CFTimeInterval pausedTime = layer.timeOffset; 
      // 1. 让CALayer的时间继续行走
      layer.speed = 1.0; 
      // 2. 取消上次记录的停留时刻 
      layer.timeOffset = 0.0; 
      // 3. 取消上次设置的时间
      layer.beginTime = 0.0; 
      // 4. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime) 
      CFTimeInterval timeSincePause = [layer   convertTime:CACurrentMediaTime() fromLayer:nil] -   pausedTime; 
      // 5. 设置相对于父坐标系的开始时间(往后退timeSincePause) 
      layer.beginTime = timeSincePause; 
}

2. CAAnimation详解

CAAnimation类常用的可以分为四种

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

** CAAnimation有很多派生类 **

CATransition 提供渐变效果:(推拉push效果,消退fade效果,揭开reveal效果)。
CAAnimationGroup 允许多个动画同时播放。
CABasicAnimation 提供了对单一动画的实现。
CAKeyframeAnimation 关键桢动画,可以定义行动路线。
CAConstraint 约束类,在布局管理器类中用它来设置属性。
CAConstraintLayoutManager 约束布局管理器,是用来将多个CALayer进行布局的.各个CALayer是通过名称来区分,而布局属性是通过CAConstraint来设置的。
CATransaction 事务类,可以对多个layer的属性同时进行修改.它分隐式事务,和显式事务。


CAAnimation的一些属性

  • duration 动画的持续时间
  • repeatCount 重复次数,无线循环可以设置HUGE_VALF或者MAXFLOAT
  • repeatDuration 重复时间
  • removedOnCompletion 默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards。
  • beginTime 可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间
  • timingFunction 速度控制函数,控制动画运行的节奏
  • delegate 动画代理
  • fillMode 决定当前对象在非active时间段的行为。(要想fillMode有效,最好设置removedOnCompletion = NO)
  • kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
  • -- kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
  • -- kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
  • -- kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态
  • CAMediaTimingFunction 速度控制函数
  • kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
  • kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
  • kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
  • kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。

CAAnimation代理方法

  • 动画开始的时候调用
- (void)animationDidStart:(CAAnimation *)anim;
  • 动画停止的时候调用
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
    

** 其实比较重要的是有多个动画的时候如何在代理方法中区分不同的动画 **
方法一:

[self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];
//动画开始时
- (void)animationDidStart:(CAAnimation *)anim{ 
  if ( [anim isEqual:[self.imageView.layer animationForKey:@"Animation"]]){ 
      NSLog(@"动画组执行了");
   }
}

把动画存储为一个属性然后再回调中比较,用来判定是哪个动画是不可行的。
方法二:

[positionAnima setValue:@"PositionAnima" forKey:@"AnimationKey"];
[transformAnima setValue:@"TransformAnima" forKey:@"AnimationKey"];
//动画结束时
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{ 
    if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]) { 
        NSLog(@"位置移动动画执行结束"); 
     } else if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"TransformAnima"])
     { 
            NSLog(@"旋转动画执行结束"); 
     }
}

所以,可以根据key中不同的值来进行区分不同的动画

3. CABasicAnimation 使用总结

CABasicAnimation提供了最基础的动画属性设置,是简单的keyframe动画性能。CABasicAnimation可以看做是一种CAKeyframeAnimation的简单动画,因为它只有头尾的关键帧(keyframe)。 我们可以创建一个CABasicAnimaiton的对象通过keyPath的方式。CABasicAnimation提供了fromValue、toValue、byValue的设置(插值)。它们三个属性定义了一个动画的轨迹,并且最少两个值不能为空。当设置了CABasicAnimation的起点与终点值后,中间的值都是通过插值方式计算出来的,插值计算是通过timingFunction来指定,timingFunction默认为空,使用liner(匀速运动)。例如,当我们设置了一个position的动画,设置了开始值PointA与结束值PointB,它们的运动先计算PointA与PointB的中间运动值PointCenter,而PointCenter是由timingFunction来指定值的,并且动画默认是直线匀速运动的。

属性说明

  • keyPath:要改变的属性名称(传字符串)
  • fromValue: KeyPath相应属性的初始值
  • toValue: keyPath相应属性的结束值

动画过程说明

  • 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
  • keyPath内容是CALayer的可动画Animatable属性
  • 如果fillMode=kCAFillModeForwards
    同时removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。

实例化

使用"animationWithKeyPath:"方法进行CABasicAnimation的实例化,并指定Layer的属性作为关键路径来注册。

// 指定position属性  
CABasicAnimation *animation =  [CABasicAnimation animationWithKeyPath:@"position"];  

设定动画

* duration        动画的时长
* repeatCount     重复的次数,不停重复设置为 HUGE_VALF
* repeatDuration  设置动画的时间,在该时间内动画一直执行,不计次数。
* beginTime       指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式
* timingFunction  设置动画的速度变化
* autoreverses    动画结束时是否执行逆动画
* fromValue       所改变属性的起始值
* toValue         所改变属性的结束时的值
* byValue         所改变属性相同起始值的改变量
* speed 改变动画的速度 可以直接设置动画上的speed属性,这样只有这个动画速度。//animation.speed = 2;
或者在layer上设置speed属性,这样在该视图上的所有动画都提速,该视图上的所有子视图上的动画也会提速。
 >  speed两点需注意的:
(1) 如果设置动画时间为4s,speed设置为2,则动画只需2s即可执行完。
(2)如果同时设置了动画的speed和layer 的speed,则实际的speed为两者相乘。
transformAnima.fromValue = @(M_PI_2);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transformAnima.autoreverses = YES;transformAnima.repeatCount = HUGE_VALF;
transformAnima.beginTime = CACurrentMediaTime() + 2;

防止动画结束后回到初始状态

只需设置removedOnCompletion、fillMode两个属性就可以了。

transformAnima.removedOnCompletion = NO;
transformAnima.fillMode = kCAFillModeForwards;

添加动画

[self.imageView.layer addAnimation:transformAnima forKey:@"A"];
------------------------------------
[positionAnima setValue:@"PositionAnima" forKey:@"AnimationKey"];

  • 一个 CABasicAniamtion 的实例对象只是一个数据模型,和他绑定到哪一个layer上是没有关系的
  • 方法addAnimation:forKey:是将 CABasicAniamtion 对象进行了 copy 操作的。所以在将其添加到一个layer上之后,我们还是将其再次添加到另一个layer上的。

fillMode属性

该属性定义了你的动画在开始和结束时的动作。默认值是 kCAFillModeRemoved。

  • kCAFillModeRemoved 设置为该值,动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动画执行完成后将会layer的改变恢复原状。
  • kCAFillModeForwards 设置为该值,动画即使之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性值是 YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO。
  • kCAFillModeBackwards 设置为该值,将会立即执行动画的第一帧,不论是否设置了 beginTime属性。观察发现,设置该值,刚开始视图不见,还不知道应用在哪里。
  • kCAFillModeBoth 该值是 kCAFillModeForwards 和 kCAFillModeBackwards的组合状态

timingFunction值得设定

(1)使用方法functionWithName:方法。
(2)使用方法functionWithControlPoints: : : :实现。

  • kCAMediaTimingFunctionLinear 传这个值,在整个动画时间内动画都是以一个相同的速度来改变。也就是匀速运动。
  • kCAMediaTimingFunctionEaseIn 使用该值,动画开始时会较慢,之后动画会加速。
  • kCAMediaTimingFunctionEaseOut 使用该值,动画在开始时会较快,之后动画速度减慢。
  • kCAMediaTimingFunctionEaseInEaseOut 使用该值,动画在开始和结束时速度较慢,中间时间段内速度较快。

解决有时视图会闪动一下的问题,我们可以将layer的属性值设置为我们的动画最后要达到的值,然后再给我们的视图添加layer动画。


一些常用的animationWithKeyPath值的总结

transform.scale   比例转化  @(0.8)
transform.scale.x   宽的比例    @(0.8)
transform.scale.y   高的比例    @(0.8)
transform.rotation.x    围绕x轴旋转  @(M_PI)
transform.rotation.y    围绕y轴旋转  @(M_PI)
transform.rotation.z    围绕z轴旋转  @(M_PI)
cornerRadius            圆角的设置    @(50)
opacity              透明度        @(0.7)
contentsRect.size.width 横向拉伸缩放  @(0.4)最好是0~1之间的
backgroundColor      背景颜色的变化    (id)[UIColor purpleColor].CGColor
bounds    大小,中心不变   [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
position    位置(中心点的改变)  [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents    内容,比如UIImageView的图片 imageAnima.toValue = (id)[UIImage imageNamed:@"to"].CGImage;

4. CAKeyFrameAnimation详解

对 CAKeyFrameAnimation的使用与CABasicAnimation大同小异,有些属性是共通的。KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等。因此,聪明的 你应该知道了,在下图中共有5个关键帧(图3中的ABCDE)。上个关键帧到当前关键帧之间的路径与当前关键帧相联系,比如AB->B,我们可 以对AB进行定义动画定义,而自定义要通过众多CAKeyFrameAnimation的属性达到目的。

1.png

(1)values属性
values属性指明整个动画过程中的关键帧点,例如上例中的A-E就是通过values指定的。需要注意的是,起点必须作为values的第一个值。
(2)path属性
作 用与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定 时,path会覆盖values,即values属性将被忽略。例如上述例子等价于代码中values方式的path设置方式为:

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, rectLayer.position.x - 15, rectLayer.position.y - 15);
CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y);
CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y + 100);
CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y + 100);
CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y);
rectRunAnimation.path = path;
CGPathRelease(path);

(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段就是用了淡入淡出效果。记住,这是一个数组,你有几个子路径就应该传入几个元素

5.CAAnimationGroup详解

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

属性解析:

animations:用来保存一组动画对象的NSArray默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间

代码实例

6. CATransition详解

CATransition * transition = [CATransition animation]; transition.duration = 1.0;//动画间隔 
transition.type = kCATransitionMoveIn;//主要种类,决定动画效果 
transition.startProgress = 0.0;//开始 transition.endProgress = 1.0;//结束 
transition.subtype = kCATransitionFromRight;//次要种类,决定动画方向 
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];//时间函数
[self.imageview.layer addAnimation:transition forKey:@"ToNext"]; 
self.imageview.image = nextImage;

type (动画类型)

  • 公开API
fade          淡出效果             kCATransitionFade
movein        新视图移动到旧视图上   kCATransitionMoveIn
push          新视图推出旧视图      kCATransitionPush
reveal        移开旧视图显示新视图   kCATransitionReveal  
  • 私有API (私有API只能通过字符串访)
cube            立方体翻转效果
oglFlip         翻转效果    
suckEffect       收缩效果   
rippleEffect       水滴波纹效果   
pageCurl           向上翻页效果   
pageUnCurl       向下翻页效果 
cameralIrisHollowOpen   摄像头打开效果 
cameraIrisHollowClose   摄像头关闭效果

subtype (动画子类)

kCATransitionFromRight  从右侧转场
kCATransitionFromLeft    从左侧转场
kCATransitionFromTop      从顶部转场
kCATransitionFromBottom   从底部转场

推荐阅读更多精彩内容