Set contents of CALayer to animated GIF?

前端 未结 3 887
我在风中等你
我在风中等你 2021-01-16 10:02

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:

3条回答
  •  广开言路
    2021-01-16 10:37

    - (CAKeyframeAnimation *)createGIFAnimation:(NSData *)data{
    
        CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)(data), nil);
        int frameCount =(int) CGImageSourceGetCount(src);
    
        // Total loop time
        float time = 0;
    
        // Arrays
        NSMutableArray *framesArray = [NSMutableArray array];
        NSMutableArray *tempTimesArray = [NSMutableArray array];
    
        // Loop
        for (int i = 0; i < frameCount; 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;
    }
    

    according to mahal its should be done

提交回复
热议问题