加载JIF动画的几种方法

1、使用UIWebView

// 读取gif图片数据 注意:传入nil参数可能有警告
    NSData *data = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"001" ofType:@"gif"]];    
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,200,200)];
    [webView loadData:data MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
    [self.view addSubview:webView];

使用UIWebView的弊端在于,不能设置Gif动画的播放时间。

2、将Gif拆分成多张图片,使用UIImageView播放

UIImageView *gifImageView = [[UIImageView alloc] initWithFrame:CGRectMake((SCREENWIDTH-100)/2, (SCREENHEIGHT-NAVGATIONBRHEIGHT-200)/2, 100, 200)];
NSArray *array = @[[UIImage imageNamed:@"shuaxin1"],[UIImage imageNamed:@"shuaxin2"],[UIImage imageNamed:@"shuaxin3"],[UIImage imageNamed:@"shuaxin4"]];

gifImageView.animationImages = array; //获取Gif图片列表
gifImageView.animationDuration = 1.5;     //执行一次完整动画所需的时长
gifImageView.animationRepeatCount = 1;  //动画重复次数
[gifImageView startAnimating];
[self.view addSubview:gifImageView];

3、使用SDWebImage

SDWebImage这个库里有一个UIImage+GIF的类别,里面为UIImage扩展了三个方法

//name直接传GIF的名字,不用带扩展名
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;

+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;

- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;

举例:

NSString *path = [[NSBundle mainBundle] pathForResource:@"gifTest" ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage sd_animatedGIFWithData:data];
gifImageView.image = image; 

可以在 .m 文件中设置动画的持续时间

4、加载网络Gif文件

加载网络的Gif文件就简单多了。最简单的方法,我们只需要使用SDWebImage 的 sd_setImageWithURL:这个方法传入Gif文件是url地址即可。
纠其原因:稍微仔细看了SDWebImage内部实现就可以清楚,大概是以下几个步骤:

1、SDWebImage根据url将Gif文件下载下来,格式为一个NSData
2、如果判断是Gif格式,则会调用 sd_animatedGIFWithData: 将Data转换成我们需要的Gif格式
3、通过上面的方法二即可显示出Gif图片

5、写一个解析Gif的工具类,解决每一帧画面并遵循每一帧所对应的显示时间进行播放

程序的思路如下:

  1. 首先使用ImageIO库中的CGImageSource家在Gif文件。
  2. 通过CGImageSource获取到Gif文件中的总的帧数,以及每一帧的显示时间。
  3. 通过CAKeyframeAnimation来完成Gif动画的播放。

.H文件

//
//  SvGifView.h
//  SvGifSample
//
//  Created by maple on 3/28/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
//


\#import 

@interface SvGifView : UIView


/*
 * @brief desingated initializer
 */

- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;

/*
 * @brief start Gif Animation
 */
- (void)startGif;

/*
 * @brief stop Gif Animation
 */
- (void)stopGif;

/*
 * @brief get frames image(CGImageRef) in Gif
 */

+ (NSArray*)framesInGif:(NSURL*)fileURL;


@end

.M文件

//
//  SvGifView.m
//  SvGifSample
//
//  Created by maple on 3/28/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
//

\#import "SvGifView.h"
\#import 
\#import 

/*
 * @brief resolving gif information
 */

void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime,CGFloat *gifWidth, CGFloat *gifHeight)
{
    CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);

    // get frame count
    size_t frameCount = CGImageSourceGetCount(gifSource);
    for (size_t i = 0; i < frameCount; ++i) {
        // get each frame
        CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
        [frames addObject:(id)frame];
        CGImageRelease(frame);

        // get gif info with each frame
        NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);
        NSLog(@"kCGImagePropertyGIFDictionary %@", [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary]);

        // get gif size
        if (gifWidth != NULL && gifHeight != NULL) {
            *gifWidth = [[dict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];
            *gifHeight = [[dict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];
        }

        // kCGImagePropertyGIFDictionary中kCGImagePropertyGIFDelayTime,kCGImagePropertyGIFUnclampedDelayTime值是一样的
        NSDictionary *gifDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
        [delayTimes addObject:[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime]];

        if (totalTime) {
            *totalTime = *totalTime + [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];
        }
    }
}

@interface SvGifView() {
    NSMutableArray *_frames;
    NSMutableArray *_frameDelayTimes;

    CGFloat _totalTime;         // seconds
    CGFloat _width;
    CGFloat _height;
}

@end

@implementation SvGifView


- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;
{
    self = [super initWithFrame:CGRectZero];
    if (self) {

        _frames = [[NSMutableArray alloc] init];
        _frameDelayTimes = [[NSMutableArray alloc] init];

        _width = 0;
        _height = 0;

        if (fileURL) {
            getFrameInfo((CFURLRef)fileURL, _frames, _frameDelayTimes, &_totalTime, &_width, &_height);
        }

        self.frame = CGRectMake(0, 0, _width, _height);
        self.center = center;
    }

    return self;
}

+ (NSArray*)framesInGif:(NSURL *)fileURL
{
    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:3];
    NSMutableArray *delays = [NSMutableArray arrayWithCapacity:3];

    getFrameInfo((CFURLRef)fileURL, frames, delays, NULL, NULL, NULL);

    return frames;
}

- (void)startGif
{
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];

    NSMutableArray *times = [NSMutableArray arrayWithCapacity:3];
    CGFloat currentTime = 0;
    int count = _frameDelayTimes.count;
    for (int i = 0; i < count; ++i) {
        [times addObject:[NSNumber numberWithFloat:(currentTime / _totalTime)]];
        currentTime += [[_frameDelayTimes objectAtIndex:i] floatValue];
    }
    [animation setKeyTimes:times];

    NSMutableArray *images = [NSMutableArray arrayWithCapacity:3];
    for (int i = 0; i < count; ++i) {
        [images addObject:[_frames objectAtIndex:i]];
    }

    [animation setValues:images];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
    animation.duration = _totalTime;
    animation.delegate = self;
    animation.repeatCount = 5;

    [self.layer addAnimation:animation forKey:@"gifAnimation"];
}

- (void)stopGif
{
    [self.layer removeAllAnimations];
}

// remove contents when animation end
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    self.layer.contents = nil;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}


@end 

你可能感兴趣的:(iOS-OC)