zoukankan      html  css  js  c++  java
  • iOS 动画 (二)

    在上一篇专题文章【原】iOSCoreAnimation动画系列教程(一):CABasicAnimation【包会】中 我们学习了iOS核心动画CoreAnimation中CABasicAnimation动画的使用方法。CABasicAnimation已经可以应付 一些比较简单的应用场景了,比如view的平移出现、淡入淡出等。但是在有些情况下直线的运动并不能满足我们的需要,因此有必要学习进阶版的核心动画,那 就是CAKeyFrameAnimation。

      在上一篇专题中我们提到,CAAnimation可分为以下四种:

    1.CABasicAnimation
    通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
    2.CAKeyframeAnimation
    Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
    3.CAAnimationGroup
    Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时执行,如何按顺序执行我到时候再讲。
    4.CATransition
    这个就是苹果帮开发者封装好的一些动画,
    

    CABasicAnimation算是CAKeyFrameAnimation的 特殊情况,即不考虑中间变换过程,只考虑起始点与目标点就可以了。而CAKeyFrameAnimation则更复杂一些,允许我们在起点与终点间自定义 更多内容来达到我们的实际应用需求!比如,手机淘宝中,当你添加物品到购物车后会出现将物品抛到购物车的效果,这种效果实现起来也不难,无非是先绘制抛物 线在执行position以及scale的GroupAnimation而已,以下图1是我模仿该功能小玩出来的一个demo示例,感兴趣的话你可以自己 实现一下试试:D.

                        

                            图1                                              图2 

    下面我们以实现“小圆球绕矩形跑道循环跑动”为目标开始对CAKeyFrameAnimation的介绍,如图2所示。小圆球的运动轨迹可分为四段,每段的运动速度不同,第一段中先慢后快再慢。先贴上源码方便后面分析:

     

     1 //绕矩形循环跑
     2 - (void)initRectLayer
     3 {
     4     rectLayer = [[CALayer alloc] init];
     5     rectLayer.frame = CGRectMake(15, 200, 30, 30);
     6     rectLayer.cornerRadius = 15;
     7     rectLayer.backgroundColor = [[UIColor blackColor] CGColor];
     8     [self.view.layer addSublayer:rectLayer];
     9     CAKeyframeAnimation *rectRunAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    10     //设定关键帧位置,必须含起始与终止位置
    11     rectRunAnimation.values = @[[NSValue valueWithCGPoint:rectLayer.frame.origin],
    12                                 [NSValue valueWithCGPoint:CGPointMake(320 - 15,
    13                                                                       rectLayer.frame.origin.y)],
    14                                 [NSValue valueWithCGPoint:CGPointMake(320 - 15,
    15                                                                       rectLayer.frame.origin.y + 100)],
    16                                 [NSValue valueWithCGPoint:CGPointMake(15, rectLayer.frame.origin.y + 100)],
    17                                 [NSValue valueWithCGPoint:rectLayer.frame.origin]];
    18     //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
    19     rectRunAnimation.keyTimes = @[[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.6],
    20                                   [NSNumber numberWithFloat:0.7], [NSNumber numberWithFloat:0.8],
    21                                   [NSNumber numberWithFloat:1]];
    22     rectRunAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
    23                                          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
    24                                          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],
    25                                          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
    26     rectRunAnimation.repeatCount = 1000;
    27     rectRunAnimation.autoreverses = NO;
    28     rectRunAnimation.calculationMode = kCAAnimationLinear;
    29     rectRunAnimation.duration = 4;
    30     [rectLayer addAnimation:rectRunAnimation forKey:@"rectRunAnimation"];
    31 }

     

                        

     

                                          图3

    对 CAKeyFrameAnimation的使用与CABasicAnimation大同小异,有些属性是共通的,因此小翁建议你先阅读上一篇文章。 KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等。因此,聪明的 你应该知道了,在上述例子中共有5个关键帧(图3中的ABCDE)。上个关键帧到当前关键帧之间的路径与当前关键帧相联系,比如AB->B,我们可 以对AB进行定义动画定义,而自定义要通过众多CAKeyFrameAnimation的属性达到目的。CAKeyFrameAnimation的使用中 有以下主要的属性需要注意,有些属性可能比较绕比较难以理解,我会结合图片进行必要的说明。

    (1)values属性

    values属性指明整个动画过程中的关键帧点,例如上例中的A-E就是通过values指定的。需要注意的是,起点必须作为values的第一个值。

    (2)path属性

    作 用与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定 时,path会覆盖values,即values属性将被忽略。例如上述例子等价于代码中values方式的path设置方式为:

    1     CGMutablePathRef path = CGPathCreateMutable();
    2     CGPathMoveToPoint(path, NULL, rectLayer.position.x - 15, rectLayer.position.y - 15);
    3     CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y);
    4     CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y + 100);
    5     CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y + 100);
    6     CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y);
    7     rectRunAnimation.path = path;
    8     CGPathRelease(path);

    (3)keyTimes属性

    该 属性是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间 为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的14。当然,我们也可以传个数组让物体快慢结 合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....

    (4)timeFunctions属性

    用过UIKit层动画的同学应该对这个属性不陌生,这个属性用以指定时间函数,类似于运动的加速度,有以下几种类型。上例子的AB段就是用了淡入淡出效果。记住,这是一个数组,你有几个子路径就应该传入几个元素

    1 kCAMediaTimingFunctionLinear//线性
    2 kCAMediaTimingFunctionEaseIn//淡入
    3 kCAMediaTimingFunctionEaseOut//淡出
    4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
    5 kCAMediaTimingFunctionDefault//默认

    (5)calculationMode属性

    该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似

    1 const kCAAnimationLinear//线性,默认
    2 const kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上
    3 const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
    4 const kCAAnimationCubic//平均,同上
    5 const kCAAnimationCubicPaced//平均,同上

    此外,动画的暂停与开始可以通过下面的方式做到:

     1 -(void)pauseLayer:(CALayer*)layer
     2 {
     3     CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
     4     layer.speed = 0.0;
     5     layer.timeOffset = pausedTime;
     6 }
     7 
     8 -(void)resumeLayer:(CALayer*)layer
     9 {
    10     CFTimeInterval pausedTime = [layer timeOffset];
    11     layer.speed = 1.0;
    12     layer.timeOffset = 0.0;
    13     layer.beginTime = 0.0;
    14     CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    15     layer.beginTime = timeSincePause;
    16 }

    更多更详细的关于这些属性的介绍可以进一步阅读此文

    关于CAKeyFrameAnimation的介绍基本结束了,在文章的最后,开源一个小翁封装的抛物动画代码,上文的图1就是在这份代码的基础上实现的:

    ThrowLineTool.h
    ThrowLineTool.m
    使用方法
  • 相关阅读:
    爬虫之移动端数据爬取
    Python网络爬虫之图片懒加载技术、selenium和PhantomJS
    iOS-类方法
    iOS-二进制,十进制,十六进制的相互转换
    iOS-category
    iOS-.h和.m文件
    iOS-关于@property和@synthesize
    自定义控件-使用frame和代码的自定义UI控件
    跨平台开发
    GitHub探索
  • 原文地址:https://www.cnblogs.com/fyongbetter/p/5632956.html
Copyright © 2011-2022 走看看