• UI进阶--核心动画(Core Animation)


    Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍,使用它需要先添加QuartzCore.framework和引入对应的框架<QuartzCore/QuartzCore.h>。
    开发步骤:
    ①初始化一个动画对象(CAAnimation)并设置一些动画相关属性
    ②添加动画对象到层(CALayer)中,开始执行动画
    CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties)


    通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就能触发动画了。通过调用removeAnimationForKey可以停止层中的动画
    Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。

    CAAnimation继承结构:

    CAAnimation:

    所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
    属性解析:(红色代表来自CAMediaTiming协议的属性)
    duration:动画的持续时间
    repeatCount:动画的重复次数
    repeatDuration:动画的重复时间
    removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
    fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
    beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间
    timingFunction:速度控制函数,控制动画运行的节奏
    • 1.kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
    • 2.kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
    • 3.kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
    • 4.kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为
    delegate:动画代理
     
    CAPropertyAnimation:
    是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
    属性解析:
    keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@”position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果.
      CABasicAnimation:
      CAPropertyAnimation的子类
      属性解析:
      fromValue:keyPath相应属性的初始值
      toValue:keyPath相应属性的结束值
      随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
      如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0).
    示例代码:
      1 //
      2 //  ViewController.m
      3 //  CABasicAnimation
      4 //
      5 //  Created by xiaomoge on 15/1/6.
      6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
      7 //
      8 
      9 #import "ViewController.h"
     10 
     11 @interface ViewController ()
     12 @property (weak, nonatomic) IBOutlet UIView *testView;
     13 
     14 @end
     15 
     16 @implementation ViewController
     17 
     18 - (void)viewDidLoad {
     19     [super viewDidLoad];
     20     //[self testBasicTranslation];
     21 }
     22 
     23 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     24     //[self testBasicTranslation];
     25     //[self testBasicRotation];
     26     //[self testBasicScale];
     27     //[self testBasicBounds];
     28     [self testPosition];
     29 }
     30 #pragma mark - 平移动画
     31 - (void)testBasicTranslation {
     32     //创建动画对象
     33     CABasicAnimation *translationAni = [CABasicAnimation animation];
     34     //设置动画的属性
     35     
     36     //keyPath 是一个路径式, 或者说是类型
     37     translationAni.keyPath = @"transform.translation.y";
     38     //动画开始位置
     39     translationAni.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
     40     //动画结束的位置
     41     //translationAni.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];;
     42     //动画位置增加的值
     43    //translationAni.byValue = @100;
     44     //动画位置增加到的值
     45     translationAni.toValue = @200;
     46     translationAni.duration = 5;
     47     //添加动画进view的layer
     48     [self.testView.layer addAnimation:translationAni forKey:nil];
     49     
     50 }
     51 #pragma mark - 旋转动画
     52 - (void)testBasicRotation {
     53     //创建一个动画对象
     54     CABasicAnimation *rotationAni = [CABasicAnimation animation];
     55     //设置动画的属性
     56     rotationAni.keyPath = @"transform.rotation";
     57     rotationAni.byValue = @(M_PI_4);
     58     rotationAni.duration = 3;
     59     //添加动画
     60     [self.testView.layer addAnimation:rotationAni forKey:nil];
     61 }
     62 #pragma mark - 缩放动画
     63 - (void)testBasicScale {
     64     //创建一个动画对象
     65     CABasicAnimation *scaleAni = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];
     66     //设置动画的属性
     67     scaleAni.byValue = @1.5;
     68     scaleAni.duration = 3;
     69     //添加动画
     70     [self.testView.layer addAnimation:scaleAni forKey:nil];
     71 }
     72 #pragma mark - bounds
     73 - (void)testBasicBounds {
     74     //创建一个动画对象
     75     CABasicAnimation *boundsAni = [CABasicAnimation animationWithKeyPath:@"bounds"];
     76     //设置动画的属性
     77     boundsAni.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 300, 400)];
     78     boundsAni.duration = 3;
     79     //添加动画
     80     [self.testView.layer addAnimation:boundsAni forKey:nil];
     81 }
     82 #pragma mark - position 
     83 - (void)testPosition {
     84     //创建一个动画对象
     85     CABasicAnimation *positionAni = [CABasicAnimation animationWithKeyPath:@"position"];
     86     //设置动画的属性
     87     positionAni.byValue = [NSValue valueWithCGPoint:CGPointMake(15, 15)];
     88     positionAni.duration = 3;
     89     //如果想保持动画后的效果:方案1:代理(- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag方法)
     90     //positionAni.delegate = self;
     91     //方案2:设置动画的两个属性
     92     positionAni.removedOnCompletion = NO;//动画对象不要移除
     93     positionAni.fillMode = kCAFillModeForwards;//保存当前状态
     94     
     95     //添加动画
     96     [self.testView.layer addAnimation:positionAni forKey:nil];
     97 }
     98 #pragma mark - 动画代理方法
     99 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    100     self.testView.frame = CGRectMake(115, 115,self.testView.frame.size.width,self.testView.frame.size.height);
    101 }
    102 @end
     CAKeyframeAnimation:
     CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
     属性解析:
     values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
     path:可以设置一个CGPathRefCGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略
     keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的
     CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation。
     示例代码:
     1 //
     2 //  ViewController.m
     3 //  CAKeyframeAnimation
     4 //
     5 //  Created by xiaomoge on 15/1/6.
     6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 @property (weak, nonatomic) IBOutlet UIView *imgView;
    13 
    14 @end
    15 
    16 @implementation ViewController
    17 
    18 - (void)viewDidLoad {
    19     [super viewDidLoad];
    20     // Do any additional setup after loading the view, typically from a nib.
    21 }
    22 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    23     //创建一个帧动画,类型为position
    24     CAKeyframeAnimation *keyframeAni = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    25     //设置动画的属性
    26     NSValue *val1 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
    27     NSValue *val2 = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
    28     //values是一个数组,存储的都是一个轨迹
    29     keyframeAni.values = @[val1,val2];
    30     //动画重复次数
    31     keyframeAni.repeatCount = 3;
    32     //kCAMediaTimingFunctionEaseIn 先慢后快
    33     //kCAMediaTimingFunctionEaseOut 先快后慢
    34     //kCAMediaTimingFunctionLinear 线性匀速
    35     //kCAMediaTimingFunctionEaseInEaseOut 中间快两边慢
    36     //创建动画的节奏
    37     keyframeAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    38     //创建一个路径
    39     CGMutablePathRef path = CGPathCreateMutable();
    40     CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    41     //绘制一个路径
    42     CGPathAddEllipseInRect(path, Nil, CGRectMake(0, 0, screenW, screenW));
    43     //设置动画的path属性
    44     keyframeAni.path = path;
    45     //c语言的create后,还要记得销毁
    46     CGPathRelease(path);
    47     //动画的时间
    48     keyframeAni.duration = 3;
    49     //添加动画进图层
    50     [self.imgView.layer addAnimation:keyframeAni forKey:nil];
    51 }
    52 @end
     
    CAAnimationGroup:
    CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行
    属性解析:
    animations:用来保存一组动画对象的NSArray
    默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间。
    示例代码:
     1 //
     2 //  ViewController.m
     3 //  CAAnimationGroup
     4 //
     5 //  Created by xiaomoge on 15/1/6.
     6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 //storyboard上拖拉的一个UIView控件
    13 @property (weak, nonatomic) IBOutlet UIView *imgView;
    14 
    15 @end
    16 
    17 @implementation ViewController
    18 
    19 - (void)viewDidLoad {
    20     [super viewDidLoad];
    21     // Do any additional setup after loading the view, typically from a nib.
    22 }
    23 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    24     //创建一个组动画
    25     CAAnimationGroup *groupAni = [CAAnimationGroup animation];
    26     
    27     //添加平移动画
    28     CABasicAnimation *transilationAni = [CABasicAnimation animationWithKeyPath:@"position"];
    29    // transilationAni.duration = 5;
    30     transilationAni.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 400)];
    31     
    32     //添加旋转动画
    33     CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    34     rotation.toValue =@(M_PI_2);
    35     //rotation.duration = 5;
    36     
    37     //添加缩放动画
    38     CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    39     scale.byValue = @1.2;
    40     //scale.duration = 5;注意,动画的时间由组动画来控制即可
    41 
    42     //组动画的属性设置,添加进动画组
    43     groupAni.animations = @[transilationAni,rotation,scale];
    44     groupAni.duration = 5;
    45     [self.imgView.layer addAnimation:groupAni forKey:nil];
    46 }
    47 @end
     
    CATransition:
    CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
    UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果
    属性解析:
    type:动画过渡类型
    subtype:动画过渡方向
    startProgress:动画起点(在整体动画的百分比)
    endProgress:动画终点(在整体动画的百分比)
    动画过渡类型:
     1 fade     //交叉淡化过渡(不支持过渡方向) kCATransitionFade
     2 push     //新视图把旧视图推出去  kCATransitionPush
     3 moveIn   //新视图移到旧视图上面   kCATransitionMoveIn
     4 reveal   //将旧视图移开,显示下面的新视图  kCATransitionReveal
     5 cube     //立方体翻滚效果
     6 oglFlip  //上下左右翻转效果
     7 suckEffect   //收缩效果,如一块布被抽走(不支持过渡方向)
     8 rippleEffect //滴水效果(不支持过渡方向)
     9 pageCurl     //向上翻页效果
    10 pageUnCurl   //向下翻页效果
    11 cameraIrisHollowOpen  //相机镜头打开效果(不支持过渡方向)
    12 cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向)

    示例代码:

     1 //
     2 //  ViewController.m
     3 //  CATransition
     4 //
     5 //  Created by xiaomoge on 15/1/6.
     6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 //storyboard上拖拉的一个UIImageView控件,大小和屏幕一致
    13 @property (weak, nonatomic) IBOutlet UIImageView *imgView;
    14 //storyboard上拖拉的一个UITapGestureRecognizer控件
    15 - (IBAction)tapView:(UITapGestureRecognizer *)sender;
    16 //图片数组
    17 @property (nonatomic,strong) NSMutableArray *imgs;
    18 //图片的索引
    19 @property (nonatomic,assign) NSInteger imgIndex;
    20 @end
    21 
    22 @implementation ViewController
    23 #pragma mark - 懒加载图片
    24 - (NSMutableArray *)imgs {
    25     if (!_imgs) {
    26         _imgs = [NSMutableArray array];
    27         for (int i = 0; i < 9; i++) {
    28             NSString *imgName = [NSString stringWithFormat:@"%d.jpg",i + 1];
    29             [_imgs addObject:imgName];
    30         }
    31     }
    32     return _imgs;
    33 }
    34 - (void)viewDidLoad {
    35     [super viewDidLoad];
    36     // Do any additional setup after loading the view, typically from a nib.
    37 }
    38 #pragma mark - 手势识别事件
    39 - (IBAction)tapView:(UITapGestureRecognizer *)sender {
    40     
    41     CGPoint poi = [sender locationInView:sender.view];//取得手势的触摸点
    42     if (poi.x <= sender.view.bounds.size.width * 0.5) {
    43         [self previous];//如果触摸点在左边,执行上一张事件
    44     }else {
    45         [self next];//否则执行下一张事件
    46     }
    47 }
    48 #pragma mark - 上一张事件
    49 - (void)previous {
    50     if (self.imgIndex == 0) return;//如果当前是第一张,直接返回
    51     self.imgIndex --;
    52     self.imgView.image =[UIImage imageNamed: self.imgs[self.imgIndex]];//更换对应的图片
    53     [self addCaTransition];//执行动画
    54 }
    55 #pragma mark - 下一张事件
    56 - (void)next {
    57     if (self.imgIndex == self.imgs.count - 1) return;//如果是最后一张,直接返回
    58     self.imgIndex ++;
    59     self.imgView.image =[UIImage imageNamed: self.imgs[self.imgIndex]];//更换对应的图片
    60     [self addCaTransition];//执行动画
    61 }
    62 #pragma mark - 创建动画事件
    63 - (void)addCaTransition {
    64     //创建一个动画对象
    65     CATransition *transition = [CATransition animation];
    66     //设置动画的属性
    67     transition.type = @"push";//动画的类型,可选用其他
    68     transition.duration = 2;//动画的时间
    69     //添加进图层
    70     [self.imgView.layer addAnimation:transition forKey:nil];
    71 }
    72 @end
  • 相关阅读:
    prism.js——让网页中的代码更好看
    WebAPI之FormData
    ES6背记手册
    搭建本地的百度脑图
    webpack到底是干什么用的?
    浅拷贝和深拷贝
    vue 中使用 watch 的各种问题
    跳一跳外挂的python实现--OpenCV步步精深
    Opencv基础课必须掌握:滑动条做调色盘 -OpenCV步步精深
    Opencv稍微高级点的鼠标事件-OpenCV步步精深
  • 原文地址:https://www.cnblogs.com/xiaomoge/p/4207388.html
Copyright © 2020-2023  润新知