美文网首页iOS开发UIiOS的UI进阶
iOS动画进阶 - CAKeyframeAnimation实现过

iOS动画进阶 - CAKeyframeAnimation实现过

作者: attackGiant | 来源:发表于2017-09-12 15:43 被阅读231次

    ··~~~~因为工作原因需要对动画有所了解,由于之前用的很少,这方面的知识很匮乏,所以借此机会深入的了解了下关于动画方面的知识,由于没有找到好的动画效果,就高仿了一个用CAKeyframeAnimation实现的过山车动画~~~~~~~呜呜呜

    1505202465905.jpg

    动态果图:http://ww4.sinaimg.cn/large/006tNbRwgw1f53ahi8vslg30if0a8e81

    项目中主要用到的类

    • CAShapeLayer
    • CAGradientLayer
    • CAKeyframeAnimation
    渐变的天空背景色使用CAGradientLayer类来生成两种或更多的渐变平滑的颜色,草坪和轨道使用CAShapeLayer配合UIBezierPath(贝塞尔曲线)完成,云朵、大地和大树可以通过CALayer设置contents属性来实现(注:如果给CALayer设置color或imaeg属性时,需要将color转换为CGColor,image转换为CGImage,不然图片或颜色不显示---),云朵和过山车的动画可以使用CAKeyframeAnimation来实现,是不是看起来好简单~~~~

    ---------------------------------下面是每个类的功能介绍---------------------------------

    CAShapeLayer

    • 1、CAShapeLayer是一种特殊的层,可以在上面渲染图形。
    • 2、CAShapeLayer继承自CALayer,可使用CALayer的所有属性。
    • 3、CAShapeLayer需要和贝塞尔曲线配合使用才有意义,贝塞尔曲线为其提供渲染的图形。
    • 4、使用CAShapeLayer与贝塞尔曲线可以实现不再view的drawRect方法中画出一些想要的图形。
    CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类, CAShapeLayer相当于使用画笔直接在图层上绘制想要的图片,通过GPU来渲染图形,如果使用drawRect来绘制图形是调用CoreGraphics框架中得方法,占用CPU,消耗性能大(那简直要卡爆了)。使用CAShapeLayer你可以指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图形,最后CAShapeLayer就自动渲染出来了。当然,你也可以用Core Graphics直接向原始的CALyer的内容中绘制一个路径,相比直下,使用CAShapeLayer有以下一些优点:
    • 渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
    • 高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
    • 不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉
    • 不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。

    使用CAShapeLayer来绘制草地的代码:

     //第一块草坪
        self.shapeLayer = [CAShapeLayer layer];
        //通过贝塞尔曲线绘制路径
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, kScreenWidth - 20)];//设置曲线的起点
        [path addLineToPoint:CGPointMake(0, kScreenWidth - 100)];//连线到某点
        [path addQuadCurveToPoint:CGPointMake(kScreenHeight / 3.0, kScreenWidth - 20) controlPoint:CGPointMake(kScreenHeight / 6.0, kScreenWidth - 100)];//设置终点和控制点,控制点越小绘制的图形越大越高
        
        self.shapeLayer.path = path.CGPath;
        self.shapeLayer.fillColor = [UIColor colorWithRed:82.0/255.0 green:177.0/255.0 blue:44.0/255.0 alpha:1.0].CGColor;//设置填充色
        [self.backV.layer addSublayer:self.shapeLayer];
        
        //第二块草坪
        
        CAShapeLayer *shapeLayer2 = [CAShapeLayer layer];
        UIBezierPath *path2 = [UIBezierPath bezierPath];
        [path2 moveToPoint:CGPointMake(0, kScreenWidth - 20)];
        [path2 addQuadCurveToPoint:CGPointMake(kScreenHeight, kScreenWidth - 60) controlPoint:CGPointMake(kScreenHeight / 2.0, kScreenWidth - 150)];
        [path2 addLineToPoint:CGPointMake(kScreenHeight, kScreenWidth - 20)];
        shapeLayer2.path = path2.CGPath;
    
        shapeLayer2.fillColor = [UIColor colorWithRed:92.0/255.0 green:195.0/255.0 blue:52.0/255.0 alpha:1.0].CGColor;
        [self.backV.layer addSublayer:shapeLayer2];
    

    效果图:

    006tNbRwgw1f53ba1snf4j30ij0agtc7.jpg

    CAGradientLayer

    CAGradientLayer 简介

    • CAGradientLayer是CALayer图层类的子类,用于处理渐变色的层结构。
    • CAGradientLayer的渐变色可以做隐式动画。
    • CAGradientLayer和CAShapeLayer配合使用可实现复杂效果。
    • CAGradientLayer可以用作PNG的遮罩效果。
    • CAGradientLayer 坐标系统
    1339729-c2ec801415d3aca9.png
    • CAGradientLayer的坐标系统是从坐标(0,0)到(1,1)绘制的矩形。
    • CAGradientLayer的frame值的size不为正方形的话,坐标系统会被拉伸。
    • CAGradientLayer的startPoint与endPoint会直接影响颜色的绘制方向。
    • CAGradientLayer的颜色分割点是以0~1的比例来计算的,颜色分割点为渐变色开始或终止的地方。

    CAGradientLayer 属性介绍

    • colors:渐变颜色数组
    • locations:渐变颜色的区间分布(分割点),locations的数组长度和colors一致。这个属性可不设,默认是nil,系统会平均分布颜色如果有特定需要可设置,数组设置为0 ~ 1之间单调递增。
    • startPoint:映射locations中起始位置,用单位向量表示。比如(0, 0)表示从左上角开始变化。默认值是:(0.5, 0.0)。
    • endPoint:映射locations中结束位置,用单位向量表示。比如(1, 1)表示到右下角变化结束。默认值是:(0.5, 1.0)。
    • type:默认值是kCAGradientLayerAxial,表示按像素均匀变化。

    使用CAGradientLayer来实现了项目中天空背景的绘制,效果图:

    006tNbRwgw1f53ax28scyj30ij09w74d.jpg

    天空背景代码:

     //初始化 背景
        
         self.CAGLayer = [CAGradientLayer layer];
         self.CAGLayer.frame = self.backV.bounds;
        //设置渐变的颜色
         self.CAGLayer.colors = @[(id)[UIColor colorWithRed:178.0/255.0 green:226.0/255.0 blue:248.0/255.0 alpha:1.0].CGColor,
                          (id)[UIColor colorWithRed:232.0/255.0 green:244.0/255.0 blue:193.0/255.0 alpha:1.0].CGColor];
        //设置渐变的方向 自左上到右下
         self.CAGLayer.startPoint = CGPointMake(0, 0);
         self.CAGLayer.endPoint = CGPointMake(1, 1);
        [self.backV.layer addSublayer: self.CAGLayer];
    

    CAKeyframeAnimation

    CAKeyframeAnimation简介

    • CAKeyframeAnimation又称关键帧动画
    • CAKeyframeAnimation是抽象类CAPRopertyAnimation的子类,可以直接使用
    • 通过values与path两个属性指定动画属性

    注意事项

    • 若指定了path属性,则values属性将被忽略
    • CABasicAnimation相当于只有两个关键帧的CAKeyframeAnimation

    CAKeyframeAnimation 属性介绍

    • values(NSArray *)存放关键帧的多个值,类似于CABasicAnimation的fromValue与toValue值
    • path(CGPathRef)动画的执行路径,可以通过绘图的方式绘制路径
    • keyTimes(NSArray *)每个关键帧的执行时间,类型为NSNumber类型,若不指定,则所有的关键帧平分动画的duration时长
    • timingFunctions(NSArray *)速度控制函数数组
    • calculationMode(NSString *)指定关键帧的动画属性,若指定该值,则keyTimes与timingFunctions属性值将被忽略,默认为:kCAAnimationLinear
    • rotationMode(NSString *)指定旋转模式,默认为nil
    CAKeyframeAnimation类为对象提供了关键帧动画的功能。你创建一个CAKeyframeAnimation对象使用animationWithKeyPath:指定属性的关键路径,你可以指定要使用关键帧的值来控制时间和动画的行为。我们可以通过CAKeyframeAnimation来实现过山车在轨道上的的动画和云朵的动画:
    1505206576473.jpg
    代码如下:
     CALayer *carLayer = [CALayer layer];
        carLayer.frame = CGRectMake(0, 0, 17, 11);
        UIImage *image = [UIImage imageNamed:@"othercar"];
        CGImageRef imageRef = image.CGImage;
        carLayer.contents = (__bridge id _Nullable)(imageRef);
    
        UIBezierPath *bluePath  = [UIBezierPath bezierPath];
        bluePath.lineCapStyle = kCGLineCapRound;
        bluePath.lineJoinStyle = kCGLineCapRound;
        [bluePath  moveToPoint:CGPointMake(kScreenWidth2 +10, kScreenHeight2 - 7)];
        [bluePath addLineToPoint:CGPointMake(kScreenWidth2 + 10, kScreenHeight2 - 77)];
        [bluePath addQuadCurveToPoint:CGPointMake(kScreenWidth2 / 1.8, kScreenHeight2 - 77) controlPoint:CGPointMake(kScreenWidth2 - 120, 193)];
        [bluePath addArcWithCenter:CGPointMake(kScreenWidth2 / 1.9, kScreenHeight2 - 140) radius:63 startAngle:0.5*M_PI endAngle:2.5*M_PI clockwise:true];
        
        [bluePath addCurveToPoint:CGPointMake(0, kScreenHeight2 - 107) controlPoint1:CGPointMake(kScreenWidth2 /1.8 - 60, kScreenHeight2 - 67) controlPoint2:CGPointMake(150, kScreenHeight2 /2.3 -7)];
        [bluePath addLineToPoint:CGPointMake(-100, kScreenHeight2 +7)];
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];//简单的创建一个带路径的动画效果,比较粗糙
        animation.path = bluePath.CGPath;
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];//CAMediaTiming协议定义了在一段动画内用来控制逝去时间的属性的集合,CALayer和CAAnimation都实现了这个协议,所以时间可以被任意基于一个图层或者一段动画的类控制。
        //      速度控制函数(CAMediaTimingFunction)
        //    1.kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
        //    2.kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
        //    3.kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
        //    4.kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
        animation.duration = 6;//动画持续时间
        animation.beginTime = begintime;
        animation.repeatCount = MAXFLOAT;
        animation.autoreverses =false;
        animation.calculationMode = kCAAnimationCubicPaced;//自动计算
        animation.rotationMode = kCAAnimationRotateAuto;//动画角度自动调整
        [self.view.layer addSublayer:carLayer];
        [carLayer addAnimation:animation forKey:@"carAnimation"];
    

    附上github地址欢迎Star~~~~~,至此过山车动画完成。。

    参考文档:CALayer中文翻译(Swift版)

    COPY原链接

    相关文章

      网友评论

      • e6515e5fc40c:想请教一下,是怎么控制整列火车可以在圆上弯曲的?是因为各个车厢独立控制吗?
      • 好尼桑:copy的能不能附上原链接?
      • 歪冒:写的可以的
        attackGiant:@歪冒 蟹蟹夸奖
      • attackGiant:欢迎小伙伴们批评指导!!!!(表太狠哦。。。)

      本文标题:iOS动画进阶 - CAKeyframeAnimation实现过

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