美文网首页iOS Developer
iOS动画(Core Animation)

iOS动画(Core Animation)

作者: NexTOne | 来源:发表于2016-07-08 18:37 被阅读198次

    Core Animation(核心动画)简介

    • 它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果。
    • Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
    • Core Animation是直接作用在CALayer上的,并非UIView。
    CAAnimation是所有动画类的父类,但是它不能直接使用,应该使用它的子类。
    • CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
    • 能用的动画类只有4个子类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup

    平移动画

    示例代码

    @interface ViewController () 
    
    @property (nonatomic, weak) CALayer *layer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 50, 50);
        layer.position = CGPointMake(50, 50);
        // 设置layer的锚点为左上角(0,0)
        layer.anchorPoint = CGPointMake(0, 0);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.cornerRadius = 10;
        
        [self.view.layer addSublayer:layer];
        self.layer = layer;
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 创建核心动画
        CABasicAnimation *anim = [CABasicAnimation animation];
        
        // 要执行什么样的动画
        anim.keyPath = @"position";
        
        // 通过动画,将layer从哪儿移动到哪儿
        anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        anim.toValue  = [NSValue valueWithCGPoint:CGPointMake(200, 300)];
        
        // 完成动画所需要消耗的时间
        anim.duration  = 2;
        
        // 动画执行完毕之后不删除动画
        anim.removedOnCompletion = NO;
        // 保存动画的最新状态
        anim.fillMode = kCAFillModeForwards;
        
        // 设置动画的代理,可以监听动画的执行过程,这里设置控制器为代理
        anim.delegate = self;
        
        //添加核心动画到layer
        [self.layer addAnimation:anim forKey:nil];
    }
    
    - (void)animationDidStart:(CAAnimation *)anim {
        NSLog(@"执行前: %@", NSStringFromCGPoint(self.layer.position));
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        NSLog(@"执行后: %@", NSStringFromCGPoint(self.layer.position));
    }
    
    验证图层的属性值还是动画执行前的初始值{50,50},并没有真正被改变
    • 实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变
    position.png

    缩放动画

    代码示例:

    @interface ViewController () 
    
    @property (nonatomic, weak) CALayer *layer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 50, 50);
        layer.position = CGPointMake(50, 50);
        // 设置layer的锚点为左上角(0,0)
        layer.anchorPoint = CGPointMake(0, 0);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.cornerRadius = 10;
        
        [self.view.layer addSublayer:layer];
        self.layer = layer;
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 创建核心动画
        CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"bounds"];
        
        // 设置动画执行时间
        anim.duration  = 2;
        
        // 动画执行完毕之后不删除动画
        anim.removedOnCompletion = NO;
        // 保存动画的最新状态
        anim.fillMode = kCAFillModeForwards;
        
        // 修改属性,执行动画
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
        //添加核心动画到layer
        [self.layer addAnimation:anim forKey:nil];
    }
    

    旋转动画

    示例代码:

    @interface ViewController () 
    
    @property (nonatomic, weak) CALayer *layer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        CALayer *layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 150, 50);
        layer.position = CGPointMake(50, 50);
        // 设置layer的锚点为左上角(0,0)
        layer.anchorPoint = CGPointMake(0, 0);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.cornerRadius = 10;
        
        [self.view.layer addSublayer:layer];
        self.layer = layer;
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
         // 创建动画
        CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
        // 设置动画执行时间
        anim.duration  = 2;
      // 修改属性,执行动画
        anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 1, 1, 0)];
        // 动画执行完毕之后不删除动画
        anim.removedOnCompletion = NO;
        // 保存动画的最新状态
        anim.fillMode = kCAFillModeForwards;
        [self.layer addAnimation:anim forKey:nil]; 
    }
    

    关键帧动画简介

    是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
    示例代码:

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *customerView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 创建动画
        CAKeyframeAnimation *keyAnim = [CAKeyframeAnimation animation];
        // 要执行什么样的动画
        keyAnim.keyPath = @"position";
        NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
        NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 100)];
        NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
        NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 200)];
        NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
        keyAnim.values=@[value1,value2,value3,value4,value5];
        
        // 动画执行完毕之后不删除动画
        keyAnim.removedOnCompletion = NO;
        // 保存动画的最新状态
        keyAnim.fillMode = kCAFillModeForwards;
         // 设置动画执行时间
        keyAnim.duration = 3.0;
        // 设置代理
        keyAnim.delegate = self;
        // 设置动画的节奏
        keyAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        //添加核心动画到layer
        [self.customerView.layer addAnimation:keyAnim forKey:nil];
    }
    
    - (void)animationDidStart:(CAAnimation *)anim {
        NSLog(@"开始动画");
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        NSLog(@"结束动画");
    }
    

    停止动画(可以通过path属性,让layer在指定的轨迹上运动)

    代码示例如下

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *customerView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 创建动画
        CAKeyframeAnimation *keyAnim = [CAKeyframeAnimation animation];
        // 平移
        keyAnim.keyPath = @"position";
        // 创建一条路径
        CGMutablePathRef path = CGPathCreateMutable();
        // 设置一个圆的路径
        CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));
        keyAnim.path = path;
        
        //有create就一定要有release
        CGPathRelease(path);
        
        // 动画执行完毕之后不删除动画
        keyAnim.removedOnCompletion = NO;
        // 保存动画的最新状态
        keyAnim.fillMode = kCAFillModeForwards;
        // 设置动画执行时间
        keyAnim.duration = 3.0;
        
        // 设置动画的节奏
        keyAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        //添加核心动画到layer
        [self.customerView.layer addAnimation:keyAnim forKey:@"next"];
    
    }
    
    - (IBAction)stop {
        // 停止self.customView.layer上名称标示为nextone的动画
        [self.customerView.layer removeAnimationForKey:@"next"];
    }
    

    图标抖动

    #define angle2Radian(angle) ((angle)/180.0*M_PI)
    
    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 创建动画
        CAKeyframeAnimation *keyAnim = [CAKeyframeAnimation animation];
        // 要执行什么样的动画
        keyAnim.keyPath = @"transform.rotation";
        // 设置动画时间
        keyAnim.duration = 0.1;
        // 设置图片抖动弧度
        // 把度数转换为弧度(度数/180*M_PI)
        keyAnim.values = @[@(-angle2Radian(6)), @(angle2Radian(6)), @(-angle2Radian(6))];
        // 设置动画的重复次数
        keyAnim.repeatCount = MAXFLOAT;
        // 动画执行完毕之后不删除动画
        keyAnim.removedOnCompletion = NO;
        // 保存动画的最新状态
        keyAnim.fillMode = kCAFillModeForwards;
        [self.iconImageView.layer addAnimation:keyAnim forKey:nil];
    
    }
    

    转场动画和组动画

    • CATransition(转场动画)是CAAnimation的子类,能够为层提供移出屏幕和移入屏幕的动画效果
    • UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果

    属性解析:
    type:动画过渡类型
    subtype:动画过渡方向
    startProgress:动画起点(在整体动画的百分比)
    endProgress:动画终点(在整体动画的百分比)

    代码示例

    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property (nonatomic, assign) NSInteger index;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        self.index = 1;
    }
    
    
    - (IBAction)preClick:(id)sender {
        self.index--;
        if (self.index < 1) {
            self.index = 3;
        }
        self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"Guide%ld", self.index]];
        // 创建核心动画
        CATransition *anim = [CATransition animation];
        //设置过度效果
        anim.type = @"cube";
        //设置动画的过度方向(向左
        anim.subtype = kCATransitionFromLeft;
        anim.duration = 2.0;
        [self.imageView.layer addAnimation:anim forKey:nil];
    }
    
    - (IBAction)nextClick:(id)sender {
        self.index++;
        if (self.index > 3) {
            self.index = 1;
        }
        self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"Guide%ld", self.index]];
        // 创建核心动画
        CATransition *anim = [CATransition animation];
        //设置过度效果
        anim.type = @"cube";
        //设置动画的过度方向(向左
        anim.subtype = kCATransitionFromRight;
        anim.duration = 2.0;
        // 设置动画的起点
        anim.startProgress = 0.5;
        [self.imageView.layer addAnimation:anim forKey:nil];
    }
    

    动画组(平移-旋转-缩放作为一组动画一起执行)

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *iconView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 平移动画
        CABasicAnimation *a1 = [CABasicAnimation animation];
        a1.keyPath = @"transform.translation.y";
        a1.toValue = @(300);
        
        // 缩放动画
        CABasicAnimation *a2 = [CABasicAnimation animation];
        a2.keyPath = @"transform.scale";
        a2.toValue = @(0.0);
        
        // 旋转动画
        CABasicAnimation *a3 = [CABasicAnimation animation];
        a3.keyPath = @"transform.rotation";
        a3.toValue = @(M_PI_2);
        
        // 组动画
        CAAnimationGroup *groupAnim = [CAAnimationGroup animation];
        groupAnim.animations  = @[a1, a2, a3];
        
        groupAnim.duration = 3;
        groupAnim.fillMode = kCAFillModeForwards;
        groupAnim.removedOnCompletion = NO;
        
        [self.iconView.layer addAnimation:groupAnim forKey:nil];
    }
    

    UIView封装动画

    • UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持

    代码示例

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *customerView;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 首尾式动画
       [UIView beginAnimations:nil context:nil];
        //执行动画
        //设置动画执行时间
        [UIView setAnimationDuration:2.0];
        self.customerView.center=CGPointMake(200, 300);
        //设置代理
        [UIView setAnimationDelegate:self];
        //设置动画执行完毕调用的事件
        [UIView setAnimationDidStopSelector:@selector(didStopAnimation)];
    }
    
    - (void)didStopAnimation {
        NSLog(@"动画执行完毕");
    }
    

    注:UIView封装的动画执行完毕之后不会反弹。即如果是通过CALayer核心动画改变layer的位置状态,表面上看虽然已经改变了,但是实际上它的位置是没有改变的

    block动画

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *customerView;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        /*
         duration:动画的持续时间
         delay:动画延迟delay秒后开始
         options:动画的节奏控制
         animations:将改变视图属性的代码放在这个block中
         completion:动画结束后,会自动调用这个block
         */
        [UIView animateWithDuration:2.0
                              delay:3.0
                            options:UIViewAnimationOptionBeginFromCurrentState
                         animations:^{
                             self.customerView.center=CGPointMake(200, 300);
                         }
                         completion:^(BOOL finished) {
                             NSLog(@"动画执行完毕");
                         }];
        
        
    }
    

    转场动画

    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIView *customerView;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [UIView transitionWithView:self.customerView
                          duration:3.0
                           options:0
                        animations:^{
                            self.customerView.center=CGPointMake(200, 300);
                        } completion:^(BOOL finished) {
                            NSLog(@"动画执行完毕");
                        }];
    }
    

    UIImageView的帧动画

    UIImageView可以让一系列的图片在特定的时间内按顺序显示

    @interface ViewController ()
    
    @property (nonatomic, strong) NSMutableArray *images;
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation ViewController
    
    - (NSMutableArray *)images {
        if (!_images) {
            _images = [NSMutableArray array];
            for (int i = 0; i < 4; i++) {
                UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg", i]];
                [_images addObject:image];
            }
        }
        return _images;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        _imageView.userInteractionEnabled = YES;
        _imageView.animationImages = self.images;
        _imageView.animationDuration = 1.0;
        _imageView.animationRepeatCount = 0;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        if (![_imageView isAnimating]) {
            [_imageView startAnimating];
        } else {
            [_imageView stopAnimating];
        }
    }
    
    

    相关链接:
    Core Animation核心动画

    相关文章

      网友评论

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

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