iOS动画

作者: z4ywzrq | 来源:发表于2018-01-21 22:20 被阅读17次

    Core Animation简介

    Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
    Core Animation可以用在Mac OS X和iOS平台。
    Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
    要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。有关CALayer可参看之前的博客:CALayer

    Core Animation 每次添加动画时 QuartzCore 会打包其参数,然后通过进程间通信的方式传递给一个名为 backboard 的后台进程。然后该进程通过 OpenGL 渲染和处理 layer 的层级以及 layer 上的动画。最重要的一点就是该进程完全独立于你的应用,应用只会拿到动画开始和结束的回调(CAAnimationDelegate),不负责动画的渲染(显式动画除外)。也就是主线程和 CoreAnimation 不会互相影响,也就是即使主线程阻塞了,CoreAnimation 依旧在执行。

    CAAnimation

    1、CAAnimation的常用属性:
    • duration:动画的持续时间
    • repeatCount:动画的重复次数,(INFINITY,HUGE_VALF,CGFLOAT_MAX)
    • speed:表示当前对象的时间流速,如果speed是2,duration是3,那么经过1.5秒动画就播放完成了。
    • removedOnCompletion :保持动画执行后的状态。默认值为YES,动画执行完毕后,动画会自动从CALayer上移除,CALayer又会回到原来的状态
    • fillMode:播放结束后的状态
      kCAFillModeForwards:保持结束时状态
      kCAFillModeBackwards:保持开始时状态
      kCAFillModeBoth:保持两者
      kCAFillModeRemoved:移除
    • timingFunction:控制动画运行的节奏
      timingFunction可设置的值有:
      kCAMediaTimingFunctionLinear:线性匀速
      kCAMediaTimingFunctionEaseIn:缓慢进入,然后加速离开
      kCAMediaTimingFunctionEaseOut:快速进入,然后减速到达
      kCAMediaTimingFunctionEaseInEaseOut:渐进渐出,缓慢的进入,中间加速,然后减速的到达
    • delegate:动画代理,用来监听动画的执行过程
     // 动画开始执行的时候触发这个方法
     - (void)animationDidStart:(CAAnimation *)anim;
     // 动画执行完毕的时候触发这个方法
     - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
    
    2、 CALayer addAnimation

    在上篇 UIView, CALayer 中提到,当你给一个 CALayer 添加动画的时候,实并没有改变这个 layer 的实际属性。取而代之的,系统会创建一个原始 layer 的拷贝,原始 layer 为 Model Layer ,复制的 layer 则被称为 Presentation Layer 。 Presentation Layer 的属性会随着动画的进度实时改变,而 Model Layer 中对应的属性则并不会改变。也就是默认情况下系统会动画执行完后,自动移除 CAAnimation,移除之后系统就会自动销毁这个 layer 的 Presentation Layer ,只留下 Model Layer ,Model Layer 的属性其实并没有变化,一瞬间回到了动画的初始状态。要解决这种情况,你需要先把 removedOnCompletion 设 置 为 NO , 然 后 设 置 fillMode 为 kCAFillModeForwards 保持结束时状态。

    CAPropertyAnimation

    CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
    它有个NSString类型的keyPath属性,你可以指定CALayer的某个属性名为keyPath,并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@"position"为keyPath,就会修改CALayer的position属性的值,以达到平移的动画效果
    因此,初始化好CAPropertyAnimation的子类对象后,必须先设置keyPath,搞清楚要修改的是CALayer的哪个属性,执行的是怎样的动画。
    CALayer的那些属性改变支持动画效果,查看CALayer属性对应的注释,有animatable,就是支持动画的。


    CABasicAnimation

    CABasicAnimation是CAPropertyAnimation的子类,使用它可以实现一些基本的动画效果,它可以让CALayer的某个属性从某个值渐变到另一个值。下面就用CABasicAnimation实现几个简单的动画。

    • 平移动画
    
    //KeyPath:@"position":说明要修改的是CALayer的position属性,执行平移动画
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
    anim.duration = 1.5;  // 动画持续1.5s
    
    // position属性值从(50, 80)渐变到(300, 350)
    //不是直接使用CGPoint这种结构体类型,而是要先包装成NSValue对象后再使用。
    anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(50, 80)];
    anim.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 350)];
    //如果将toValue换成byValue,代表CALayer从位置(50, 80)开始向右移动300、向下移动350,也就是移动到位置(350, 430)
    
    // 设置动画的代理
    anim.delegate = self;
    
    // 保持动画执行后的状态。默认值为YES,动画执行完毕后,动画会自动从CALayer上移除,CALayer又会回到原来的状态
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    
    // 添加动画对象到图层上
    [view.layer addAnimation:anim forKey:@"translate"];
    //给动画对象起个名称,以后可以调用CALayer的removeAnimationForKey:方法根据动画名称停止相应的动画
    
    //设置动画的代理,可以监听动画的执行过程
    // 动画开始
    - (void)animationDidStart:(CAAnimation *)anim {
    }
    
    //动画结束
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    }
    
    

    平移另一种方法

    //平移
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    anim.duration = 1;
    CATransform3D form = CATransform3DMakeTranslation(350, 350, 0);
    anim.toValue = [NSValue valueWithCATransform3D:form];
    [view.layer addAnimation:anim forKey:nil];
    
    
    • 缩放动画
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"bounds"];
    anim.duration = 2;
    anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 30, 30)];
    [view.layer addAnimation:anim forKey:nil];
    //layer会从原来的尺寸变为30x30
    
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    anim.duration = 2; 
    // CALayer的宽度从0.5倍变为2倍、高度从0.5倍变为1.5倍
    anim.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 0.5, 1)];
    anim.toValue  = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2, 1.5, 1)];
    [view.layer addAnimation:anim forKey:nil];
    
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    anim.toValue = @0.5;
    anim.duration = 1.0;
    anim.repeatCount = 10;
    anim.fillMode = kCAFillModeForwards;
    anim.removedOnCompletion = NO;
    [view.layer addAnimation:anim forKey:nil];
    
    • 旋转动画
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    anim.duration = 1.5;
    // 绕着(0, 0, 1)这个向量轴顺时针旋转45°
    anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
    [view.layer addAnimation:anim forKey:nil];
    
    CAKeyframeAnimation

    CABasicAnimation和CAKeyframeAnimation都是继承自CAPropertyAnimation。CAKeyframeAnimation是核心动画里面的帧动画,它提供了按照指定的一串值进行动画,与CABasicAnimation的不同点在于他可以指定多个状态,不局限于始末状态。

    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
    animation.duration = 2;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    [view.layer addAnimation:animation forKey:nil];
    
    CAKeyframeAnimation *ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    anim.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 40, 100, 300)].CGPath;
    anim.duration = 2.0;
    anim.fillMode = kCAFillModeForwards;
    anim.repeatCount = 10;
    anim.removedOnCompletion = NO;
    //anim.calculationMode = kCAAnimationCubicPaced;
    [view.layer addAnimation:anim forKey:nil];
    

    CAKeyframeAnimation的属性解释:

    • values: 是许多值组成的数组用来进行动画的。这个属性比较特别,只有在path属性值为nil的时候才有作用

    • path:路径,可以指定一个路径,让动画沿着这个指定的路径执行。

    • cacluationMode:计算模式,其主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorPoint 和 position 进行的动画,当在平面座标系中有多个离散的点的时候,可以是离散的,也可以直线相连后进行插值计算,也可以使用圆滑的曲线将他们相连后进行插值计算.
      kCAAnimationLinear calculationMode的默认值,r自定义控制动画的时间(线性)可以设置keyTimes,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算;
      kCAAnimationDiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示;
      kCAAnimationPaced 节奏动画自动计算动画的运动时间,使得动画均匀进行,而不是按keyTimes设置的或者按关键帧平分时间,此时keyTimes和timingFunctions无效;
      kCAAnimationCubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,对于曲线的形状还可以通过tensionValues,continuityValues,biasValues来进行调整自定义,这里的主要目的是使得运行的轨迹变得圆滑,曲线动画需要设置timingFunctions
      kCAAnimationCubicPaced 看这个名字就知道和kCAAnimationCubic有一定联系,其实就是在kCAAnimationCubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keyTimes以及timingFunctions也是无效的.

    • keyTimes:一个包含若干NSNumber对象值的数组,用来区分动画的分割时机。值得注意的是,这些NSNumber对象的浮点型值在0.0~1.0之间。里面的值后一个比前一个要大或者相等。最好的结果是这个数组中的值和values里面的值或者path控制的值对应,否则可能会出现不了你想要的结果。属性为应用在每一关键帧指定应用到每一个关键帧上的计时器。该属性只在calculationMode属性被设置为kCAAnimationLinear,kCAAnimaitonDiscrete,kCAAnimationCubic时被使用。它不使用在节奏动画中。keyTimes定义了应用在每一关键帧的时间点。所有中间值的定时由定时函数控制,定时函数允许你对各个部分应用缓入或缓出曲线定时。如果你不指定任何定时函数,动画将会是线性的

    • rotationMode : 旋转样式
      kCAAnimationRotateAuto 根据路径自动旋转
      kCAAnimationRotateAutoReverse 根据路径自动翻转

    CAAnimationGroup

    CAAnimationGroup 动画组,是 CAAnimation 的子类,可以保存一组动画对象,将 CAAnimationGroup 对象加入层后,组中所有动画对象可以同时并发运行。
    animations :用来保存一组动画对象的 NSArray。默认情况下,一组动画对象是同时运行的。

        CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"position"];
        anim1.fromValue = [NSValue valueWithCGPoint:CGPointMake(15, 15)];
        anim1.toValue = [NSValue valueWithCGPoint:CGPointMake(280, 15)];
        anim1.fillMode = kCAFillModeForwards;
        anim1.removedOnCompletion = NO;
        anim1.duration = 2.0;
        
        CAKeyframeAnimation *anim2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
        anim2.values = @[@0, @(M_PI_4), @(M_PI_4 * 2.0), @(M_PI_4 * 3.0), @(M_PI_4 * 4.0)];
        anim2.fillMode = kCAFillModeForwards;
        anim2.removedOnCompletion = NO;
        anim2.calculationMode = kCAAnimationCubicPaced;
        anim2.duration = 0.5;
        
        
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.duration = 2.0;
        group.animations = @[anim1, anim2];
        group.fillMode = kCAFillModeForwards;
        group.removedOnCompletion = NO;
        
        [view.layer addAnimation:group forKey:nil];
    
    CATransition

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

        CATransition *tran = [CATransition animation];
        tran.duration = 2.0;
        tran.type = @"rotate";
        tran.subtype = kCATransitionFromRight;
        
        [view.layer addAnimation:tran forKey:nil];
        view.backgroundColor = [UIColor cyanColor];
    
    • type:转场动画的类型
      基本型:
      kCATransitionFade 交叉淡化过渡
      kCATransitionPush 新视图把旧视图推出去
      kCATransitionMoveIn 新视图移到旧视图上面
      kCATransitionReveal 将旧视图移开,显示下面的新视图

      用字符串表示的类型:
      fade push moveIn reveal 和系统自带的四种一样
      pageCurl 向上翻页效果
      pageUnCurl 向下翻页效果
      rippleEffect 水滴效果
      suckEffect 收缩效果,如一块布被抽走
      cube 立方体翻滚效果
      alignedCube 立方体翻滚效果
      flip 翻转效果
      alignedFlip 翻转效果
      oglFlip 翻转效果
      rotate 旋转
      cameraIrisHollowOpen 相机镜头打开效果
      cameraIrisHollowClose 相机镜头关闭效果
      cameraIris 相机镜头打开关闭效果

    • subtype:转场动画将要去往的方向
      kCATransitionFromRight
      kCATransitionFromLeft
      kCATransitionFromTop
      kCATransitionFromBottom

    • startProgress、endProgress: 开始和结束的位置进度,数值介于[0,1]之间,结束值一定是大于开始值的

    CASpringAnimation

    iOS9之后引入的动画类,在以前使用facebook的pop来做这种弹簧效果,它继承于CABaseAnimation,用于制作弹簧动画。

        CASpringAnimation *anim = [CASpringAnimation animationWithKeyPath:@"position"];
        anim.duration = 1;
        anim.toValue = [NSValue valueWithCGPoint:CGPointMake(220, 220)];
        anim.fillMode = kCAFillModeForwards;
        anim.removedOnCompletion = NO;
        //anim.mass = 1;
        //anim.stiffness = 100;
        
        [view.layer addAnimation:anim forKey:nil];
    
    • mass:质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大,动画的速度变慢,并且波动幅度变大

    • stiffness:刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快

    • damping:阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快

    • initialVelocity:初始速率,动画视图的初始速度大小速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反如果

    • settlingDuration:结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算通常弹簧动画的时间使用结算时间比较准确

    Reference

    Core Animation Programming Guide
    http://www.cnblogs.com/QianChia/p/6359714.html
    http://www.cocoachina.com/ios/20170124/18617.html
    https://www.jianshu.com/p/92a0661a21c6
    http://www.cnblogs.com/kenshincui/p/3972100.html

    相关文章

      网友评论

          本文标题:iOS动画

          本文链接:https://www.haomeiwen.com/subject/khixbxtx.html