gpt4 book ai didi

objective-c - 将 CALayer 的内容设置为动画 GIF?

转载 作者:行者123 更新时间:2023-12-03 17:28:02 27 4
gpt4 key购买 nike

是否可以将 CALayer 的内容设置为动画 GIF 并让它显示该动画?我知道我可以将内容设置为图像,如下所示:

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

图像会显示,但如果是动画,则动画不会显示。获取 GIF 的各个帧、获取帧速率,然后根据帧速率更改子层的内容是唯一的解决方案吗?还是有一个我忽略的更简单的方法?

最佳答案

Swift 3 版本,但更改为接收 URL(出于我自己的目的)。

func createGIFAnimation(url:URL) -> CAKeyframeAnimation?{

guard let src = CGImageSourceCreateWithURL(url as CFURL, nil) else { return nil }
let frameCount = CGImageSourceGetCount(src)

// Total loop time
var time : Float = 0

// Arrays
var framesArray = [AnyObject]()
var tempTimesArray = [NSNumber]()

// Loop
for i in 0..<frameCount {

// Frame default duration
var frameDuration : Float = 0.1;

let cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(src, i, nil)
guard let framePrpoerties = cfFrameProperties as? [String:AnyObject] else {return nil}
guard let gifProperties = framePrpoerties[kCGImagePropertyGIFDictionary as String] as? [String:AnyObject]
else { return nil }

// Use kCGImagePropertyGIFUnclampedDelayTime or kCGImagePropertyGIFDelayTime
if let delayTimeUnclampedProp = gifProperties[kCGImagePropertyGIFUnclampedDelayTime as String] as? NSNumber {
frameDuration = delayTimeUnclampedProp.floatValue
}
else{
if let delayTimeProp = gifProperties[kCGImagePropertyGIFDelayTime as String] as? NSNumber {
frameDuration = delayTimeProp.floatValue
}
}

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

// Add frame to array of frames
if let frame = CGImageSourceCreateImageAtIndex(src, i, nil) {
tempTimesArray.append(NSNumber(value: frameDuration))
framesArray.append(frame)
}

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

var timesArray = [NSNumber]()
var base : Float = 0
for duration in tempTimesArray {
timesArray.append(NSNumber(value: base))
base.add( duration.floatValue / time )
}

// From documentation of 'CAKeyframeAnimation':
// the first value in the array must be 0.0 and the last value must be 1.0.
// The array should have one more entry than appears in the values array.
// For example, if there are two values, there should be three key times.
timesArray.append(NSNumber(value: 1.0))

// Create animation
let animation = CAKeyframeAnimation(keyPath: "contents")

animation.beginTime = AVCoreAnimationBeginTimeAtZero
animation.duration = CFTimeInterval(time)
animation.repeatCount = Float.greatestFiniteMagnitude;
animation.isRemovedOnCompletion = false
animation.fillMode = kCAFillModeForwards
animation.values = framesArray
animation.keyTimes = timesArray
//animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.calculationMode = kCAAnimationDiscrete

return animation;
}

重要的事情写在“CAKeyframeAnimation”的文档中:

the first value in the array must be 0.0 and the last value must be 1.0. The array should have one more entry than appears in the values array. For example, if there are two values, there should be three key times.

所以添加了这一行:

 timesArray.append(NSNumber(value: 1.0))

还检查了使用 AVAssetExportSession 导出为视频。

请这样称呼:

if let url = Bundle.main.url(forResource: "animation", withExtension: "gif"){
let animation = createGIFAnimation(url: url)
}

关于objective-c - 将 CALayer 的内容设置为动画 GIF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24125701/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com