美文网首页动画
iOS之核心动画(Core Animation)

iOS之核心动画(Core Animation)

作者: charlotte2018 | 来源:发表于2017-03-05 19:25 被阅读69次

    CALayer与UIView的关系

    在iOS中,你能看得见摸得着的东西基本上都是UIView。
    在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。
    当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。
    换句话说,UIView本身不具备显示的功能,是它内部layer才有显示功能。

    CALayer的基本属性

        CALayer *layer = [CALayer layer];
       //layer的大小
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
       //位置
        layer.position = CGPointZero;
       //锚点
        layer.anchorPoint = CGPointZero;
       //形变,三维的,uiview是二维
        self.iconView.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
        [self.view.layer addSublayer:layer];
    
    

    View和CALayer的Frame,bounds,center 映射

    一个 Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的.

    一个 View 的 frame 只是简单的返回 Layer的 frame,View 的 Center 和 Bounds 只是直接返回layer 对应的 Position 和 Bounds。

    View中frame getter方法,bounds和center,UIView并没有做什么工作;它只是简单的各自调用它底层的CALayer的frame,bounds和position方法。

    CALayerd 的 position和anchorPoint的作用

    position用来设置CALayer在父层中的位置,以父层的左上角为原(0, 0)。

    anchorPoint 称为“定位点”、“锚点”,决定着CALayer身上的哪个点会在position属性所指的位置。以自己的左上角为原点(0, 0),它的x、y取值范围都是0~1,默认值为中心点(0.5, 0.5)。

        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.anchorPoint = CGPointZero;
        layer.position = CGPointMake(0 , 0);
        [self.view.layer addSublayer:layer];
    
    
    5E16DAF1-D214-4D60-88FE-C22F75375F23.png
        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.anchorPoint = CGPointMake(0, 1);
        layer.position = CGPointMake(100 , 100);
        [self.view.layer addSublayer:layer];
    
    
    EABC3A5D-B349-4ED8-8496-853BF93CAABF.png
    • 绿色箭头所指的就是锚点和position重合的位置。

    Core Animation核心动画结构图。

    626233-43bafe84d8aee5bf.png

    其中灰色虚线表示继承关系,红色表示遵守协议。

    核心动画中所有类都遵守CAMediaTiming协议。
    CAAnaimation是个抽象类,不具备动画效果,必须用它的子类才有动画效果。

    CAAnimationGroup和CATransition才有动画效果,CAAnimationGroup是个动画组,可以同时进行缩放,旋转(同时进行多个动画)。

    CATransition是转场动画,界面之间跳转(切换)都可以用转场动画。

    CAPropertyAnimation也是个抽象类,本身不具备动画效果,只有子类才有。

    CABasicAnimation和CAKeyframeAnimation:
    CABasicAnimation基本动画,做一些简单效果。
    CAKeyframeAnimation帧动画,做一些连续的流畅的动画。

    CAAnimation 抽象类的一些属性

    CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类。

    3648C83D-A7AB-4461-BB3F-F4AFEDC2E087.png

    fillMode属性的设置:

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

    • kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态

    • kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。

    • kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态

    速度控制函数(CAMediaTimingFunction):

    kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉

    kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开

    kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地

    kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。

    CAAnimation在分类中定义了代理方法

    @protocol CAAnimationDelegate <NSObject>
    @optional
    
    /* 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
    
    

    CAPropertyAnimation

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

    属性keyPath,通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@“position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果,需要注意的是部分属性值是不支持动画效果的,以下是具有动画效果的keyPath:

    //CATransform3D Key Paths : (example)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 : (example)position.x
         //x
         //y
    
         //CGRect Key Paths : (example)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
    
    

    CABasicAnimation——基本动画

     // 1.创建动画对象
        CABasicAnimation *anim = [CABasicAnimation animation];
        
        // 2.设置动画对象
        // keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
        anim.keyPath = @"bounds";
        
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
        anim.duration = 2.0;
        
        /**让图层保持动画执行完毕后的状态**/
        // 动画执行完毕后不要删除动画
        anim.removedOnCompletion = NO;
        // 保持最新的状态
        anim.fillMode = kCAFillModeForwards;
        
        // 3.添加动画
        [self.layer addAnimation:anim forKey:@"baseAnimal"];
    
    
    • 如果fillMode = kCAFillModeForwards同时removedOnComletion = NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。

    CAKeyframeAnimation——关键帧动画

    关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:

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

    ED2E1B32-4657-409A-B149-37C1E57D70B4.png
        CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
        
        anim.keyPath = @"position";
        
        NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
        NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(200, 100)];
        NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
        NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
        NSValue *v5 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
    
        anim.values = @[v1, v2, v3, v4,v5];
        
        anim.duration = 2.1;
        
        
        anim.removedOnCompletion = NO;
        anim.fillMode = kCAFillModeForwards;
        
        [self.redView.layer addAnimation:anim forKey:nil];
    
    
        CAKeyframeAnimation * ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddEllipseInRect(path, NULL, CGRectMake(130, 200, 100, 100));
        ani.path = path;
        CGPathRelease(path);
        ani.duration = 4.0;
        ani.removedOnCompletion = NO;
        ani.fillMode = kCAFillModeForwards;
        [self.centerShow.layer addAnimation:ani forKey:@"PostionKeyframePathAni"];
    
    

    CAAnimationGroup——动画组

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

      // 1.创建旋转动画对象
        CABasicAnimation *rotate = [CABasicAnimation animation];
        rotate.keyPath = @"transform.rotation";
        rotate.toValue = @(M_PI);
        
        // 2.创建缩放动画对象
        CABasicAnimation *scale = [CABasicAnimation animation];
        scale.keyPath = @"transform.scale";
        scale.toValue = @(0.0);
        
        // 3.平移动画
        CABasicAnimation *move = [CABasicAnimation animation];
        move.keyPath = @"transform.translation";
        move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
        
        // 4.将所有的动画添加到动画组中
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[rotate, scale, move];
        group.duration = 2.0;
        group.removedOnCompletion = NO;
        group.fillMode = kCAFillModeForwards;
        
        [self.myvie.layer addAnimation:group forKey:nil];
    
    

    CATransition——转场动画

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

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

    属性说明:

    57AF306E-935F-4EA6-A999-E4C217933AF0.png

    过渡效果设置

    626233-6c72b2e17e35b178.png
      // 转场动画
        CATransition *anim = [CATransition animation];
    //    type的enum值如下:
    //    kCATransitionFade 渐变
    //    kCATransitionMoveIn 覆盖
    //    kCATransitionPush 推出
    //    kCATransitionReveal 揭开
        anim.type = @"pageCurl";
        
    //    subtype的enum值如下:
    //    kCATransitionFromRight 从右边
    //    kCATransitionFromLeft 从左边
    //    kCATransitionFromTop 从顶部
    //    kCATransitionFromBottom 从底部
        anim.subtype = kCATransitionFromRight;
        anim.duration = 0.5;
        
    //    anim.startProgress = 0.0;
    //    
    //    anim.endProgress = 0.5;
        
        [self.view.layer addAnimation:anim forKey:nil];
    
    

    CADisplayLink

    CADisplayLink是一种以屏幕刷新频率触发的时钟机制,每秒钟执行大约60次左右。

    CADisplayLink是一个计时器,可以使绘图代码与视图的刷新频率保持同步,而NSTimer无法确保计时器实际被触发的准确时间。

    // 定义
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(hehe)];
    // 添加到主循环队列
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode: NSRunLoopCommonModes];
    

    相关文章

      网友评论

        本文标题:iOS之核心动画(Core Animation)

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