iOS CoreAnimation 逐帧动画 CADisplayLink

本文参考:http://www.cnblogs.com/kenshincui/p/3972100.html#autoid-3-0-0总结的:


逐帧动画 CADisplayLink

动画效果:


结合runloop 实现 每次屏幕刷新都会执行此方法(每秒接近60此)


在此方法更新图片, 或者更新layer的某个状态实现动画效果,感觉不到动画的停滞效果


当然UIImageView通过设置animationImages的属性, 然后startAnimating方法播放这组照片,也

可以达到逐帧的动画效果, 但是存在很大的性能问题,并且一旦设置完图片中间的过程就无法控

制了,

利用定时器NSTimer定时更新图片也可以达到逐帧的效果, 这种可以解决一次性加载多个图片

的性能问题, 而且播放也可以控制, 但是可能会因为系统执行某个方法而让动画变得断断续续

的连续性问题

这里系统提供了CADisplayLink对象, CADidsplayLink是一个定时器, 与timer不同的

是,CADidsplayLink的刷新周期同屏幕完全一致, 屏幕刷新的周期是每秒60次,使其完全感觉不

到动画的停滞情况

iOS程序在运行后就进入到一个消息循环中(这个消息循环被称为"主运行循环"), 这个循环相当

于一个死循环中, 始终等待用户输入, 将CADisplayLink加入到主运行循环队列后, 它的时钟周

期就和主运行循环保持一致, 而主运行循环周期就是屏幕刷新周期.CADidsplayLink加入到主运

行循环队列后就会循环调用目标方法, 完成逐帧动画,


这里里不得不强调的是逐帧动画性能势必较低,但是对于一些事物的运动又不得不选择使用

逐帧动画,例如人的运动,这是一个高度复杂的运动,基本动画、关键帧动画是不可能解决

的。所大家一定要注意在循环方法中尽可能的降低算法复杂度,同时保证循环过程中内存峰

值尽可能低。下面以一个鱼的运动为例为大家演示一下逐帧动画。

//
//  LinkViewController.m
//  CAKeyframeAnimation
//
//  Created by 帝炎魔 on 16/5/26.
//  Copyright © 2016年 帝炎魔. All rights reserved.
//

#import "LinkViewController.h"

#define IMAGE_COUNT 10

@interface LinkViewController ()
{
    CALayer *_layer;
    int _index;
    NSMutableArray *_images;
}

@end

@implementation LinkViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置背景
    // layer 有个属性可以直接设置内容 ----> 背景图片
    self.view.layer.contents = (id)[UIImage imageNamed:@"bg"].CGImage;
    
    // 创建图像显示图层
    _layer = [[CALayer alloc] init];
    _layer.bounds = CGRectMake(0, 0, 87, 32);
    _layer.position = CGPointMake(self.view.center.x, self.view.center.y);
    [self.view.layer addSublayer:_layer];
    
    // 由于小鱼的图片比较小, 所以直接创建
    _images = [NSMutableArray array];
    for (int i = 0; i < 10; ++i) {
        NSString *imageName = [NSString stringWithFormat:@"fish%i.png", i];
        UIImage *image = [UIImage imageNamed:imageName];
        [_images addObject:image];
    }
    
    // 定义时钟对象
    CADisplayLink *displayLink  = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)];
    
    // 添加时钟对象到主运行循环
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
    //  添加动画
    [self addAnimation];
    
    // Do any additional setup after loading the view.
}

#pragma mark ---- 添加关键帧动画 --- > 给鱼一个游动的路线
-(void)addAnimation
{
    // 1. 创建动画对象
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 430, 600);
    CGPathAddCurveToPoint(path, NULL, 100, 600, 400, 200, -10, 50);
    animation.path = path;
    
   
    
    animation.repeatCount = HUGE_VALF;
    animation.duration = 8.0;
    animation.removedOnCompletion = NO;
    
    [_layer addAnimation:animation forKey:@"fishAnimation"];
    
     CGPathRelease(path);
    
}

#pragma mark --- 每次屏幕刷新都会执行一次此方法(每秒接近60次)
- (void)step

{
    // 定义一个变量记录执行次数
    static int a = 0;
    if (++a % 10  == 0) {
        UIImage *image = _images[_index];
        _layer.contents = (id)image.CGImage; // 更新图片
        _index = (_index + 1) % IMAGE_COUNT;
    }
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


你可能感兴趣的:(ios,动画,性能,图形,Quartz2D)