美文网首页iOS -动画
动画(二) Code Animation 核心动画

动画(二) Code Animation 核心动画

作者: 圉湢 | 来源:发表于2019-04-02 15:20 被阅读0次

     一、核心动画结构及定义

          Code Animation 中文翻译为核心动画,它是一组非常强的的动画处理API,是以它能做出非常炫丽的动画效果,且往往事半功倍

        核心动画所处的位置入下图所示:

    Core Animation 结构

          可以看到,Code Animation位于UIKit的下一层,是作用在CALayer(Core Animation layer)上,相较于UIView动画,它可以实现更复杂的动画效果。

        下边我们看一下,核心动画的几个类及结构

    Code Animation类及结构

    下边分析一下上图结构:

    **1.  CAMediaTiming** 协议中定义了时间,速度,重复次数等。属性定义如下:

    beginTime -> 用来设置动画延时,若想延迟1秒,就设置为CACurrentMediaTime()+1,其中CACurrentMediaTime()为图层当前时间。

    duration -> 动画的持续时间。

    speed -> 动画速率,决定动画时间的倍率。当speed为2时,动画时间为设置的duration的1/2。

    timeOffset -> 动画时间偏移量。比如设置动画时长为3秒,当设置timeOffset为1.5时,当前动画会从中间位置开始,并在到达指定位置时,走完之前跳过的前半段动画。

    repeatCount -> 动画的重复次数。

    repeatDuration -> 动画的重复时间。

    autoreverses -> 动画由初始值到最终值后,是否反过来回到初始值的动画。如果设置为YES,就意味着动画完成后会以动画的形式回到初始值。

    fillMode -> 决定当前对象在非动画时间段的行为.比如动画开始之前,动画结束之后。

    (注:其实不只是CAAnimation遵循CAMediaTiming协议,熟悉底层结构的小伙伴们应该知道CALayer也遵循这个协议,所有在一定程度上我们可以通过控制layer本身的协议属性来控制动画节奏。)

    **2. CAAnimation** 核心动画基础类,不能直接使用。除了CAMediaTiming协议中的方法,增加了CAAnimationDelegate的代理属性等。具体如下:

    timingFunction -> 控制动画的节奏。系统提供的包括:kCAMediaTimingFunctionLinear (匀速),kCAMediaTimingFunctionEaseIn (慢进快出),kCAMediaTimingFunctionEaseOut (快进慢出),kCAMediaTimingFunctionEaseInEaseOut (慢进慢出,中间加速),kCAMediaTimingFunctionDefault (默认),当然也可通过自定义创建CAMediaTimingFunction。

    delegate -> 代理。

    removedOnCompletion -> 是否让图层保持显示动画执行后的状态,默认为YES,也就是动画执行完毕后从涂层上移除,恢复到执行前的状态,如果设置为NO,并且设置fillMode为kCAFillModeForwards,则保持动画执行后的状态。

    **3. CATransition** 转场动画,系统提供了很多酷炫效果。属性如下:

    type -> 转场动画类型。

    subtype -> 转场动画方向。

    startProgress -> 动画起点进度(整体的百分比)。

    endProgress -> 动画终点进度(整体的百分比)。

    filter -> 自定义转场。

    **4.CAPropertyAnimation** 属性动画,针对对象的可动画属性进行效果的设置,不可直接使用。添加属性具体如下:

    keyPath -> CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。

    additive -> 属性动画是否以当前动画效果为基础,默认为NO。

    cumulative -> 指定动画是否为累加效果,默认为NO。

    valueFunction -> 此属性配合CALayer的transform属性使用。

    **5.CABasicAnimation**基础动画,通过keyPath对应属性进行控制,需要设置fromValue以及toValue。添加属性如下:

    fromValue -> keyPath相应属性的初始值。

    toValue -> keyPath相应属性的结束值。

    byValue -> 在不设置toValue时,toValue = fromValue + byValue,也就是在当前的位置上增加多少。

    **6.CASpringAnimation** 带有初始速度以及阻尼指数等物理参数的属性动画。我们可以把它看成在不绝对光滑的地面上,一个弹簧拴着别小球,那么我们可以这么理解他的属性(物理知识请问一下牛顿大叔):

    mass -> 小球质量,影响惯性。

    stiffness -> 弹簧的劲度系数。

    damping -> 阻尼系数,地面的摩擦力。

    initialVelocity -> 初始速度,相当于给小球一个初始速度(可正可负,方向不同)

    settlingDuration -> 结算时间,根据上述参数计算出的预计时间,相对于你设置的时间,这个时间比较准确。

    **7.CAKeyframeAnimation** 关键帧动画,同样通过keyPath对应属性进行控制,但它可以通过values或者path进行多个阶段的控制。属性如下:

    values -> 关键帧组成的数组,动画会依次显示其中的每一帧。

    path -> 关键帧路径,动画进行的要素,优先级比values高,但是只对CALayer的anchorPoint和position起作用。

    keyTimes -> 每一帧对应的时间,如果不设置,则各关键帧平分设定时间。

    timingFunctions -> 每一帧对应的动画节奏。

    calculationMode -> 动画的计算模式,系统提供了对应的几种模式。

    tensionValues -> 动画张力控制。

    continuityValues -> 动画连续性控制。

    biasValues -> 动画偏差率控制。

    rotationMode -> 动画沿路径旋转方式,系统提供了两种模式。

    **8.CAAnimationGroup** 动画组,方便对于多动画的统一控制管理。

    animations -> 所有动画效果元素的数组。

     二 、方法与代码示例

    **1、CABasicAnimation**

    在一般的应用开发中,基础动画可以满足大部分的开发需求,主要完成对于对象指定动画属性两个Value之间的动画过度。

    +(instancetype)animationWithKeyPath:(nullable NSString *)path;

    **path:**CALayer的某个属性名,并通过这个属性的值进行修改,达到相应的动画效果。下为可选参数:

    >  CATransform3D Key Paths :

    > 旋转

    > transform.rotation.z

    > rotation.x

    > rotation.y

    > rotation.z

    > rotation

    >

    > 缩放

    > scale.x

    > scale.y

    > scale.z

    > scale

    >

    > 平移

    > translation.x

    > translation.y

    > translation.z

    > translation

    >

    > 位置

    > CGPoint Key Paths:position.x

    > x

    > y

    >

    > 位置及大小

    > CGRect Key Paths :

    > bounds.size.width

    > origin.x

    > origin.y

    > origin

    > size.width

    > size.height

    > size

    > opacity 透明度

    > backgroundColor 背景色

    > cornerRadius  圆角

    > borderWidth  边距线宽

    > contents      内容

    >   

    > 阴影

    > Shadow Key Path:

    >  shadowColor

    >  shadowOffset

    >  shadowOpacity

    >  shadowRadius

    代码示例:

    > -(void)basicAnimationWithTag:(NSInteger)tag{

    >    CABasicAnimation *basicAni = nil;

    >    switch (tag) {

    >        case 0:

    >            //初始化动画并设置keyPath

    >            basicAni = [CABasicAnimation animationWithKeyPath:@"position"];

    >            //到达位置

    >            basicAni.byValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];

    >            break;

    >        case 1:

    >            basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

    >            //到达缩放

    >            basicAni.toValue = @(0.1f);

    >            break;

    >        case 2:

    >            basicAni = [CABasicAnimation animationWithKeyPath:@"opacity"];

    >            basicAni.toValue=@(0.1f);

    >            break;

    >        case 3:

    >            basicAni = [CABasicAnimation animationWithKeyPath:@"transform"];

    >            //3D

    >            basicAni.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

    >            break;

    >        case 4:

    >            basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];

    >            //圆角

    >            basicAni.toValue=@(50);

    >            break;

    >        default:

    >            break;

    >    }

    >    //设置代理

    >    basicAni.delegate = self;

    >    //延时执行

    >    //basicAni.beginTime = CACurrentMediaTime() + 2;

    >    //动画时间

    >    basicAni.duration = 1;

    >    //动画节奏

    >    basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    >    //动画速率

    >    //basicAni.speed = 0.1;

    >    //图层是否显示执行后的动画执行后的位置以及状态

    >    //basicAni.removedOnCompletion = NO;

    >    //basicAni.fillMode = kCAFillModeForwards;

    >    //动画完成后是否以动画形式回到初始值

    >    basicAni.autoreverses = YES;

    >    //动画时间偏移

    >    //basicAni.timeOffset = 0.5;

    >    //添加动画

    >    NSString *key = NSStringFromSelector(_cmd);

    >    NSLog(@"动画的key ======= %@",key);

    >    [_animationLayer addAnimation:basicAni forKey:key];

    > }

    **2、CASpringAnimation**

    CASpringAnimation是iOS9才引入的动画类,效果类似于UIView的spring动画,不过比其增加了质量,劲度系数等属性的扩展,继承于CABaseAnimation,用法也很简单:

    >  CASpringAnimation *springAni = [CASpringAnimation animationWithKeyPath:@"position"];

    >    springAni.damping = 2;

    >    springAni.stiffness = 50;

    >    springAni.mass = 1;

    >    springAni.initialVelocity = 2;

    >    springAni.toValue = [NSValue valueWithCGPoint:CGPointMake(270, 350)];

    >    springAni.duration = springAni.settlingDuration;

    >    [_animationLayer addAnimation:springAni forKey:@"springAnimation"];

    **3.CAKeyframeAnimation**

    关键帧动画和CABasicAnimation一样是CApropertyAnimation的子类,但是CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation使用values数组可以通过(keyTimes)设置多个关键帧,同时可以利用path可以进行位置或者锚点的动画操作。代码如下

    通过values设置

    >  CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];

    > keyFrameAni.duration = 2;

    > keyFrameAni.values = @[@(-(6) / 180.0*M_PI),@((6) / 180.0*M_PI),@(-(5) / 180.0*M_PI),@((5) / 180.0*M_PI),@(-(4) / 180.0*M_PI),@((4) / 180.0*M_PI),@(-(4) / 180.0*M_PI)];

    > keyFrameAni.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1)];

    > keyFrameAni.repeatCount = 2;

    > [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];

    通过path设置

        CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position"];

        UIBezierPath *path = [UIBezierPath bezierPath];

        [path moveToPoint:_animationLayer.position;

        [path addCurveToPoint:CGPointMake(300, 500) controlPoint1:CGPointMake(100, 400) controlPoint2:CGPointMake(270, 460)];

        keyFrameAni.path = path.CGPath;

        keyFrameAni.duration = 1;

        [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];

    **4.CATransition**

    转场动画是一种显示样式向另一种显示样式过渡的效果,能制作出酷炫的效果,不过谨慎使用私有API,防止被拒的悲剧。

    >    **type的enum值如下:**

    >    kCATransitionFade 渐变

    >    kCATransitionMoveIn 覆盖

    >    kCATransitionPush 推出

    >    kCATransitionReveal 揭开

    还有一些私有动画类型,效果很炫酷,不过不推荐使用。

    转场动画效果

    subtype可取值:

    >    **subtype的enum值如下:**

    >    kCATransitionFromRight 从右边

    >    kCATransitionFromLeft 从左边

    >    kCATransitionFromTop 从顶部

    >    kCATransitionFromBottom 从底部

    代码示例

    >      CATransition *transtion = [CATransition animation];

    >    transtion.duration = 1;

    >    transtion.type = @"cube";

    >    transtion.subtype = kCATransitionFromRight;//kCATransitionFromLeft  kCATransitionFromRight

    >    _animationLayer.backgroundColor = [UIColor yellowColor].CGColor;

    >    [_animationLayer addAnimation:transtion forKey:@"transtion"];

    **5.CAAnimationGroup**

    CAAnimationGroup 是一个动画组,使用Group可以将多个动画合并一起加入到层中,Group中所有动画并发执行,可以方便地实现需要多种类型动画的场景。

    代码示例

        //弹动动画

        CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position.y"];

        CGFloat ty = _animationLayer.position.y;

        keyFrameAni.values = @[@(ty - 100),@(ty),@(ty - 50),@(ty)];

        //每一个动画可以单独设置时间和重复次数,在动画组的时间基础上,控制单动画的效果

        keyFrameAni.duration = 0.3;

        keyFrameAni.repeatCount= MAXFLOAT;

        keyFrameAni.delegate = self;

        //

        //圆角动画

        CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];

        //到达位置

        basicAni.byValue = @(_animationLayer.bounds.size.width/2);

        //

        basicAni.duration = 1;

        basicAni.repeatCount = 1;

        //

        basicAni.removedOnCompletion = NO;

        basicAni.fillMode = kCAFillModeForwards;

        //设置代理

        basicAni.delegate = self;

        //动画时间

        basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

        CAAnimationGroup *aniGroup = [CAAnimationGroup animation];

        aniGroup.animations = @[keyFrameAni,basicAni];

        aniGroup.autoreverses = YES;

        //动画的表现时间和重复次数由动画组设置的决定

        aniGroup.duration = 3;

        aniGroup.repeatCount=MAXFLOAT;

        //

        [_animationLayer addAnimation:aniGroup forKey:@"groupAnimation"];

    三、动画的暂停、恢复、加快及移除动画

    1、speed属性是指当前层动画的速率。用于将父时间缩放到本地时间,例如。

    如果速率为2,则本地时间的进展速度是父时间的两倍。

    我们可以通过设置speed =0来暂停动画:

    代码示例:

     //获取当前layer的动画媒体时间

        CFTimeInterval interval = [_animationLayer convertTime:CACurrentMediaTime() toLayer:nil];

        //设置时间偏移量,保证停留在当前位置

        _animationLayer.timeOffset= interval;

        //暂定动画

        _animationLayer.speed = 0;

    设置speed =1来恢复动画

    代码示例:

     //获取暂停的时间

        CFTimeInterval beginTime = CACurrentMediaTime() - _animationLayer.timeOffset;

        //设置偏移量

        _animationLayer.timeOffset = 0;

        //设置开始时间

        _animationLayer.beginTime= beginTime;

        //开始动画

        _animationLayer.speed = 1;

    设置speed >1来加速动画

    代码示例:

     _animationLayer.speed = 2;

    2、动画结束,我们可以移除动画

    [_animationLayer removeAllAnimations];//移除当前层所有动画

        //[_animationLayer removeAnimationForKey:@"groupAnimation"];//移除当前层上名称是groupAnimation的动画

      关于Code Animation ,就写到这里了,附demo一份GitHub - Tony-iOS-Personal/AnimationDemo: 关于动画的总结demo

    相关文章

      网友评论

        本文标题:动画(二) Code Animation 核心动画

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