将CALayer的内容设置为GIF动画? [英] Set contents of CALayer to animated GIF?

查看:357
本文介绍了将CALayer的内容设置为GIF动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将CALayer的内容设置为动画GIF并显示该动画?我知道我可以将内容设置为这样的图像:

Is it possible to set the contents of a CALayer to an animated GIF and have it display that animation? I know that I can set the contents to an image like so:

CALayer* subLayer = [CALayer layer];
NSImage *image = [[NSImage alloc] initWithData:data];
subLayer.contents = image;

将显示图像,但是如果已设置动画,则不会显示动画.是获取GIF的各个帧,获取帧率,然后根据帧率更改子层的content的唯一解决方案吗?还是我忽略了一个更简单的方法?

And the image will show, but if it's animated, the animation will not display. Is the only solution to get the individual frames for the GIF, get the frame rate, then change the content of the sublayer according to the frame rate? Or is there a much simpler method that I'm overlooking?

推荐答案

好吧,我想这并不难做到.基本上我会检查图像是否为GIF:

Well, okay, I guess this isn't that hard to do. Basically I check to see if the image is a GIF:

if ([format isEqualToString:@"gif"]){
    CAKeyframeAnimation *animation = [self createGIFAnimation:data];
    [subLayer addAnimation:animation forKey:@"contents"];
}

如您所见,我正在调用自定义的createGIFAnimation方法,如下所示:

And as you can see, I'm calling my custom createGIFAnimation method, which looks like this:

- (CAKeyframeAnimation *)createGIFAnimation:(NSData *)data{
    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData:data];
    CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)(data), nil);
    NSNumber *frameCount = [rep valueForProperty:@"NSImageFrameCount"];

    // Total loop time
    float time = 0;

    // Arrays
    NSMutableArray *framesArray = [NSMutableArray array];
    NSMutableArray *tempTimesArray = [NSMutableArray array];

    // Loop
    for (int i = 0; i < frameCount.intValue; i++){

        // Frame default duration
        float frameDuration = 0.1f;

        // Frame duration
        CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(src,i,nil);
        NSDictionary *frameProperties = (__bridge NSDictionary*)cfFrameProperties;
        NSDictionary *gifProperties = frameProperties[(NSString*)kCGImagePropertyGIFDictionary];

        // Use kCGImagePropertyGIFUnclampedDelayTime or kCGImagePropertyGIFDelayTime
        NSNumber *delayTimeUnclampedProp = gifProperties[(NSString*)kCGImagePropertyGIFUnclampedDelayTime];
        if(delayTimeUnclampedProp) {
            frameDuration = [delayTimeUnclampedProp floatValue];
        } else {
            NSNumber *delayTimeProp = gifProperties[(NSString*)kCGImagePropertyGIFDelayTime];
            if(delayTimeProp) {
                frameDuration = [delayTimeProp floatValue];
            }
        }

        // Make sure its not too small
        if (frameDuration < 0.011f){
            frameDuration = 0.100f;
        }

        [tempTimesArray addObject:[NSNumber numberWithFloat:frameDuration]];

        // Release
        CFRelease(cfFrameProperties);

        // Add frame to array of frames
        CGImageRef frame = CGImageSourceCreateImageAtIndex(src, i, nil);
        [framesArray addObject:(__bridge id)(frame)];

        // Compile total loop time
        time = time + frameDuration;
    }

    NSMutableArray *timesArray = [NSMutableArray array];
    float base = 0;
    for (NSNumber* duration in tempTimesArray){
        //duration = [NSNumber numberWithFloat:(duration.floatValue/time) + base];
        base = base + (duration.floatValue/time);
        [timesArray addObject:[NSNumber numberWithFloat:base]];
    }

    // Create animation
    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];

    animation.duration = time;
    animation.repeatCount = HUGE_VALF;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.values = framesArray;
    animation.keyTimes = timesArray;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.calculationMode = kCAAnimationDiscrete;

    return animation;
}

非常简单,尽管我希望获得一些改进技巧.

Pretty straightforward, although I would love some tips on how to improve it.

这篇关于将CALayer的内容设置为GIF动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆