ios Sprite Kit 截图?
Posted
技术标签:
【中文标题】ios Sprite Kit 截图?【英文标题】:ios Sprite Kit screengrab? 【发布时间】:2013-11-03 11:32:09 【问题描述】:我正在尝试获取其中包含 SKScene 的视图的屏幕截图。我使用的技术是:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
这适用于普通 UIView,但无论出于何种原因,它都会忽略 SKScene 中的所有精灵。
我不确定这是否是一个错误,或者 Sprite Kit 的渲染是否与 UIGraphics 分开。
问题:当 UIViews 的工作方式似乎不适用于 Sprite Kit 时,我如何获取 SKScene 的屏幕抓图,或者是否有人成功使用带有 Sprite Kit 的 UIGraphics 上下文?
【问题讨论】:
好问题。由于 SKView 使用的是 OpenGL,因此您需要使用代码来获取 OpenGL 帧缓冲区。示例:***.com/questions/11769006/… 问题是 glReadPixels 是否会返回任何有意义的内容,因为尽管您可以通过 [EAGLContext currentContext] 获取 GL 上下文,但 SKView 的 open gl 并未公开。 见***.com/a/37625473/763355 【参考方案1】:您几乎拥有它,但问题如上面评论中所述。如果您想捕获SKScene
的内容,请尝试以下操作:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
解决方法基本上是改用新方法drawViewHierarchyInRect:afterScreenUpdates
,这是我们目前最好的;请注意,它并不是很快,因此实时执行此操作并不美观。
【讨论】:
@Matt 说通过这种方法抓取一个屏幕需要多快? “不完全快速”大致相当于什么? 在我的简单测试场景中不到 500 毫秒,但如果不对您的特定场景进行基准测试就很难说。更少的精灵/动作似乎使它更快一点。如果这是一个偶然的功能,它不是一个主要问题。但是如果你想做实时处理(即模拟移动精灵的模糊效果),我怀疑这在当前的硬件上是否有效。 两种屏幕抓取方法对于移动精灵来说都太慢了。那是我以前尝试过的。现在,我只是偶尔为出现在屏幕上的视图做一次(有点像 UIAlertView)。当不处于紧密循环中时,两种屏幕抓取方法运行速度都足够快,不会被注意到。 我发现即使您对 afterScreenUpdates 说“是”,也不会应用挂起的更改(例如隐藏节点)。 (ios8.3,iPhone 4s)。屏幕截图仍然是以前的状态。但是,像这样调用屏幕抓取确实解决了它:[self runAction:[SKAction waitForDuration:0.0001] completion:^ dothescreengrab ];
【参考方案2】:
作为一种更快的替代方法,您可以在SKView
上使用textureFromNode
方法,该方法将视图图像作为SKTexture
返回。只需将 SKScene
作为参数传递:
let texture = skView.textureFromNode(scene)
或捕捉部分场景:
let texture = skView.textureFromNode(scene, crop: cropRect)
【讨论】:
【参考方案3】://1:从“someNode”获取纹理
let texture = skView.textureFromNode(someNode)
//2:从节点纹理中获取UIImage
let image = UIImage(cgImage: texture!.cgImage())
【讨论】:
【参考方案4】:Swift 的解决方案:
func getScreenshot(scene: SKScene, duration:TimeInterval = 0.0001, completion:((_ txt:SKTexture) -> Void)?)
let action = SKAction.run
let bounds = scene.view?.bounds
var image = UIImage()
UIGraphicsBeginImageContextWithOptions(bounds!.size, true, UIScreen.main.scale)
scene.view?.drawHierarchy(in: bounds!, afterScreenUpdates: true)
if let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
image = screenshot
else
assertionFailure("Unable to make a screenshot for the scene \(type(of:scene))")
completion!(SKTexture(image: image))
let wait = SKAction.wait(forDuration: duration)
let seq = SKAction.sequence([wait,action])
scene.run(seq,withKey:"getScreenshot")
用法:
getScreenshot(scene: self, completion: (txt) -> Void in
let thumbNode = SKSpriteNode(texture: txt, size:CGSize(width:300,height:224))
// do whatever you want with your screenshot..
【讨论】:
以上是关于ios Sprite Kit 截图?的主要内容,如果未能解决你的问题,请参考以下文章