iOS动画进阶 - CAKeyframeAnimation实现过山车动画

··~~~~因为工作原因需要对动画有所了解,由于之前用的很少,这方面的知识很匮乏,所以借此机会深入的了解了下关于动画方面的知识,由于没有找到好的动画效果,就高仿了一个用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原链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容