美文网首页
CoreAnimation 核心动画

CoreAnimation 核心动画

作者: yuandiLiao | 来源:发表于2017-05-16 16:55 被阅读0次

    最近总结一下CoreAnimation的基本知识。。。( CALayer Animatable Properties)

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

    先上一张图,看一下核心动画中的基本类和他们之间的关系,箭头表示继承关系。

    WechatIMG7.jpeg

    下面分一下几点介绍

    • 1.CAAnimation
    • 2.CAPropertyAnimation
    • 3.CABasicAnimation 基本动画
    • 4.CAKeyframeAnimation 关键帧动画
    • 5.CATransition 转场动画
    • 6.CAAnimationGroup 动画组

    1、CAAnimation

    CAAnimation 是核心动画中的基础抽象类,其他的都是继承自他来使用。

    CAAnimation
    provides the basic support for the [CAMediaTiming] and [CAAction]protocols. 
    You do not create instance of
    [CAAnimation]: to animate Core Animation layers or SceneKit objects, 
    create instances of the concrete subclasses [CABasicAnimation], 
    [CAKeyframeAnimation], [CAAnimationGroup], or [CATransition]
    
    

    CAAnimation遵循< CAMediaTiming >和< CAAction >协议,不能直接使用CAAnimation去实现动画效果,而是使用它的子类CABasicAnimation 、CAKeyframeAnimation、CAAnimationGroup、CATransition。

    CAMediaTiming
    可以调整动画的持续时间、重复次数、动画的速度等。
    
    CAAction
    通过响应动作的方法来实现动画
    
    看一下CAAnimation里面的API
    + (nullable id)defaultValueForKey:(NSString *)key;
    类方法:根据相对的属性key返回属性值,有点类似字典
    
    - (BOOL)shouldArchiveValueForKey:(NSString *)key;
    根据相对的属性key该属性的值返回是否可以归档。
    
    属性(部分属性是遵循CAMediaTiming协议中的)
    属性 说明
    duration 动画持续的时间,默认是0
    speed 速度比例,默认是1,如果调节为n,那么在动画持续时间内会加速执行n次
    beginTime 开始时间 ,默认是0, 若想延迟ns,就设置为CACurrentMediaTime()+n,CACurrentMediaTime()为图层的当前时间
    timeOffset 时间偏移,用来暂停动画使用
    repeatCount 动画重复的次数,默认为0,无限循环可以设置HUGE_VALF或者MAXFLOAT
    repeatDuration 动画重复的时间间隔,默认0
    autoreverses 倒向动画,默认是NO,如果是Yes,动画正向执行后,会倒向执行一次
    removedOnCompletion 默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
    fillMode 决定动画开始之前或者结束之后的形态
    timingFunction 速度控制函数,控制动画运行的节奏,可以使用该类中的类方法:
    + (instancetype)functionWithName:(NSString *)name;
    name传入上面的类型创建一个CAMediaTimingFunction对象
    fillMode属性
    • kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态,即动画停止的状态,不过要配合removedOnCompletion属性设置为NO使用才有效果,不然没效果。

    • kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。动画结束后,layer会恢复到之前的状态

    • kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态,不过要配合removedOnCompletion属性设置为NO使用才有效果,不然没效果

    • kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态

    timingFunction属性
    • kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
    • kCAMediaTimingFunctionEaseIn渐进):动画缓慢进入,然后加速离开
    • kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
    • kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
    • kCAMediaTimingFunctionDefault:默认的(线性):匀速
    CAAnimation的代理方法
    @interface NSObject (CAAnimationDelegate)
    
    /* Called when the animation begins its active duration. */
    // 动画开始时调用
    - (void)animationDidStart:(CAAnimation *)anim;
    
    /* Called when the animation either completes its active duration or
     * is removed from the object it is attached to (i.e. the layer). 'flag'
     * is true if the animation reached the end of its active duration
     * without being removed. */
    // 动画结束后调用
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
    
    @end
    

    2.CAPropertyAnimation

    CAPropertyAnimation继承自CAAnimation,也是一个抽象类,是CABasicAnimation和CAKeyframeAnimation的父类,不能直接使用来生成动画效果。

    keyPath

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

    /* Creates a new animation object with its `keyPath' property set to
     * 'path'. */
    
    + (instancetype)animationWithKeyPath:(nullable NSString *)path;
    
    /* The key-path describing the property to be animated. */
    
    @property(nullable, copy) NSString *keyPath;
    
    keyPath类型 动画效果
    transform.rotation.z Z轴旋转
    transform.rotation.x X轴旋转
    transform.rotation.y Y轴旋转
    transform.scale.x 宽的比例转换
    transform.scale.y 高的比例转换
    opacity 透明度
    backgroundColor 背景色
    anchorPoint 定位点,锚点,默认中心点(0.5, 0.5)
    borderColor 边框颜色
    borderWidth 边框宽度
    bounds 大小
    contents 内容
    contentsRect 内容矩形
    cornerRadius 圆角
    frame 位置
    hidden 隐藏
    mask 标记
    maskToBounds 切割
    position 位置
    shadowOffset 阴影偏移
    shadowColor 阴影颜色
    shadowRadius 阴影角度
    shadowOpacity 阴影透明度
    strokeEnd 颜色从无到有
    strokeStart 颜色从有到无

    3.CABasicAnimation 基本动画

    继承自CAPropertyAnimation,基本动画。主要的效果是keyPath里面的,指定keyPath相应属性的初始值和keyPath相应属性的结束值。然后执行动画。

    keyPath类型 动画效果
    fromValue keyPath相应属性的初始值
    toValue keyPath相应属性的结束值

    动画过程说明:
    随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。
    keyPath内容是CALayer的可动画Animatable属性。

    如果fillMode = kCAFillModeForwards同时removedOnComletion = NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
    fillMode = kCAFillModeForwards同时removedOnComletion = NO要同时设定才有效

    -(void)createCAAnimation
    {
        //核心动画是作用在CALayer层的,所以先创建一个layer来承载动画
        CALayer *layer = [[CALayer alloc] init];
        layer.bounds = CGRectMake(0, 0, 100, 100);
        //layer没有center的属性,而是position
        layer.position = self.view.center;
        layer.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5].CGColor;
        [self.view.layer addSublayer:layer];
        
        //创建一个CAAnimation
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        //属性
        //动画持续的时间,默认是0 ,    animation.duration = 5;
        //速度比例,默认是1,如果调节为n,那么在动画持续时间内会加速执行n次
        animation.speed = 1;
        //开始时间 ,默认是0,若想延迟ns,就设置为CACurrentMediaTime()+n,CACurrentMediaTime()为图层的当前时间
        animation.beginTime = 0;
        //时间偏移,用来暂停动画使用
        animation.timeOffset = 0;
        //动画重复的次数,默认为0,无限循环可以设置HUGE_VALF或者MAXFLOAT
        animation.repeatCount = 0;
        //动画重复的时间间隔,默认0
        animation.repeatDuration = 0;
        //倒向动画,默认是NO,如果是Yes,动画正向执行后,会倒向执行一次
        animation.autoreverses = NO;
        //默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
        animation.removedOnCompletion = YES;
        //决定动画开始之前或者结束之后的形态
        animation.fillMode = kCAFillModeRemoved;
        //速度控制函数,控制动画运行的节奏
        CAMediaTimingFunction *timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        animation.timingFunction = timingFunction;
        //开始
        animation.fromValue = @(M_PI);
        //结束
        animation.toValue = @(M_PI/4);
        //为layer加上动画
        [layer addAnimation:animation forKey:@"ANIMATION"];
    }
    
    

    4. CAKeyframeAnimation 关键帧动画

    和CABasicAnimation一样继承自CAPropertyAnimation,可以理解为CABasicAnimation的升级版。

    • CABasicAnimation只能指定首尾两个keyPath,然后动画从fromValue执行到toValue。
    • CAKeyframeAnimation可以指定动画的keypath到一个values数组中,然后依次执行。
    属性 说明
    values NSArray对象。里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
    path 可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,那么values将被忽略
    keyTimes 可以为对应的关键帧指定对应的时间点,每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的
    timingFunctions 每个帧的运动类型,NSArray中存放CAMediaTimingFunction对象,个数要比values中的少一个。因为动画的真实个数要比设置的value少一个。
    calculationMode 该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似
    rotationMode
    calculationMode
    • kCAAnimationLinear//线性,默认
    • kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上
    • kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
    • kCAAnimationCubic//平均,同上
    • kCAAnimationCubicPaced//平均,同上
    rotationMode
    • kCAAnimationRotateAuto
    • kCAAnimationRotateAutoReverse
    -(void)createValuesAnimation
    {
        CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        //设置路径
        keyframeAnimation.values = [[NSArray alloc] initWithObjects:
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.center.y)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.origin.y+89)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.origin.y+89)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.center.y)],
                                     [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.size.height-25)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.size.height-25)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
    
                                    nil];
        //整个动画的时长
        keyframeAnimation.duration = 10;
        //每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同
        keyframeAnimation.keyTimes = @[@(0),@(0.2),@(0.4),@(0.5),@(0.55),@(0.7),@(0.9),@(1)];
        keyframeAnimation.repeatCount = MAXFLOAT;
        [self.layer addAnimation:keyframeAnimation forKey:nil];
        [self.view.layer addSublayer:self.layer];
    
    }
    
    -(void)createPathAnimation
    {
        CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
        //创建一个路径
        CGMutablePathRef path = CGPathCreateMutable();
        //添加圆形
        //CGPathAddEllipseInRect(path, NULL, CGRectMake(50, 90, 200, 200));
        //矩形
        CGPathAddRect(path, NULL, CGRectMake(50, 90, 200, 200));
    
        //设置路径
        keyframeAnimation.path = path;
    
        //释放路径
        CGPathRelease(path);
        
        //设置动画时间
        keyframeAnimation.duration = 3;
        //原路线返回
        // keyframeAnimation.autoreverses = YES;
          keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
        
        //设置重复次数
        keyframeAnimation.repeatCount = MAXFLOAT;
        //匀速kCAAnimationCubicPaced
        keyframeAnimation.calculationMode = kCAAnimationCubicPaced;
        [self.layer addAnimation:keyframeAnimation forKey:nil];
        [self.view.layer addSublayer:self.layer];
    }
    

    5.CATransition 转场动画

    继承自CAAnimation,切换页面的动画。

    属性 说明
    type 动画类型下面会列出各种类型
    subtype 方向
    startProgress 从什么地方开始动画,默认动画0到1
    endProgress 从什么地方结束动画,默认动画0到1
    type 说明
    开放的四种基本效果
    kCATransitionPush 推入效果
    kCATransitionMoveIn 移入效果
    kCATransitionReveal 截开效果
    kCATransitionFade 渐入渐出效果
    私有的效果
    cube 方块
    suckEffect 三角
    rippleEffect 水波抖动
    pageCurl 上翻页
    pageUnCurl 下翻页
    oglFlip 上下翻转
    cameraIrisHollowOpen 镜头快门开
    cameraIrisHollowClose 镜头快门关
    subtype的类型
    • kCATransitionFromRight 从右边开始
    • kCATransitionFromLeft 从左边来时
    • kCATransitionFromTop 从上面开始
    • kCATransitionFromBottom 从下面开始
    - (void)push
    {
        //创建一个转场动画
        CATransition *stansition = [CATransition animation];
        //设置动画时间
        stansition.duration = 1;
        //设置类型
        stansition.type = @"cube";
        stansition.subtype = kCATransitionFromRight;
        //添加动画
        [self.navigationController.view.layer addAnimation:stansition forKey:nil];
        
        NextViewController *nextVC = [[NextViewController alloc] init];
        [self.navigationController pushViewController:nextVC animated:YES];  
    }
    

    6.CAAnimationGroup 动画组

    多个动画的组合,即可以把多个动画放在animations数组中,然后同时执行多个动画。

    -(void)createAnimationGroup
    {
        //创建一个动画组
        CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
        //动画时间,如果动画组中的时间没有设置是不行的,如果设置了动画组的时间,然后里面的动画没有设置时间, 那么则以动画组的时间为准,如果里面的具体动画也设置了时间,那么以具体的动画设置的时间为准
        animationGroup.duration = 10;
        //创建一个基础动画
        CABasicAnimation *basicAnimaiton = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
        basicAnimaiton.toValue = @(M_PI);
        
        //创建一个帧动画
        CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        //设置路径
        keyframeAnimation.values = [[NSArray alloc] initWithObjects:
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.center.y)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.origin.y+89)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.origin.y+89)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.center.y)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.size.height-25)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.size.height-25)],
                                    [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                    
                                    nil];
        //每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同
        keyframeAnimation.keyTimes = @[@(0),@(0.2),@(0.4),@(0.5),@(0.55),@(0.7),@(0.9),@(1)];
        //将两个动画添加到动画组中
        animationGroup.animations = @[basicAnimaiton,keyframeAnimation];
        [self.layer addAnimation:animationGroup forKey:nil];
        [self.view.layer addSublayer:self.layer];
    }
    
    

    相关文章

      网友评论

          本文标题:CoreAnimation 核心动画

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