【发布时间】:2021-08-20 14:01:17
【问题描述】:
如何在 scenekit 中显示 GIF 图片。我有下面的代码,但它不显示图像。场景是一片空白。
func displayGIF() {
if let url = Bundle.main.url(forResource: "circles", withExtension: "gif"){
let animation = createGIFAnimation(url: url)
let layer = CALayer()
layer.bounds = CGRect(x: 0, y: 0, width:600, height:200)
layer.add(animation!, forKey: "contents")
let material = SCNMaterial()
material.isDoubleSided = true
material.diffuse.contents = layer
let plane = SCNPlane(width: 5, height: 5)
plane.materials = [material]
let node = SCNNode(geometry: plane)
self.scenekitView.allowsCameraControl = true
self.scenekitView.cameraControlConfiguration.allowsTranslation = true
self.scenekitView.scene?.rootNode.addChildNode(node)
}
}
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 += 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 = CAMediaTimingFillMode.forwards
animation.values = framesArray
animation.keyTimes = timesArray
//animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.calculationMode = CAAnimationCalculationMode.discrete
return animation;
}
【问题讨论】:
-
我不能 100% 确定这是您的
createGIFAnimation(url:)函数还是SCNScene代码。你能用简单的test.jpg替换circles.gif看看它是否有效吗?如果是这样,我假设错误可能存在于您的displayGIF()函数中,否则我敢打赌错误存在于createGIFAnimation(url:)