
SCNVIEw1包含Node1.目标是在没有Node1的情况下捕获SCNVIEw1.
但是,将afterScreenUpdates设置为true(或false)无效:屏幕截图包含Node1,无论如何.
有什么问题?
Node1.hIDden = truelet screenshot = turnVIEwToImage(SCNVIEw1,opaque: false,afterUpdates: true)// Save screenshot to diskfunc turnVIEwToImage(targetVIEw: UIVIEw,opaque: Bool,afterUpdates: Bool = false) -> UIImage { UIGraphicsBeginImageContextWithOptions(targetVIEw.bounds.size,opaque,UIScreen.mainScreen().scale) let context = UIGraphicsGetCurrentContext() CGContextSetInterpolationQuality(context,CGInterpolationQuality.High) targetVIEw.drawVIEwHIErarchyInRect(targetVIEw.bounds,afterScreenUpdates: afterUpdates) let image = UIGraphicsGetimageFromCurrentimageContext() UIGraphicsEndImageContext() return image}解决方法 我们在这里处理两个不一定通信的系统:SceneKit渲染引擎和试图捕获屏幕截图的UIKit / CoreGraphics绘图系统.当您隐藏SCNNode时,它不会立即使重绘的视图无效,就像隐藏UIVIEw子视图一样,因此将afterScreenUpdates设置为true在此时没有效果.在节点被标记为隐藏之后,在我们知道SceneKit渲染循环已经完成一次之后,并且在视图准备好在屏幕上重绘之后,我们可以捕获屏幕截图.我们可以通过为SCNVIEw( SCNSceneRendererDelegate)创建SCNSceneRendererDelegate来监听渲染循环中的事件.我们可以实现渲染器:dIDRenderScene:atTime:delegate方法. 将委托分配给场景视图(scnVIEw.delegate = self).
当您想要进行屏幕捕获时,隐藏节点并设置一个布尔标志,该标志与委托的范围相同为true:
Node1.hIDden = truescreenCaptureFlag = true // screenCaptureFlag is a controller property
然后你将实现你的委托:
func renderer(renderer: SCNSceneRenderer,dIDRenderScene scene: SCNScene,atTime time: NSTimeInterval) { if screenCaptureFlag { screenCaptureFlag = false // unflag let scnVIEw = self.vIEw as! SCNVIEw // dispatch asynchronously to main queue // Will run once SCNVIEw is ready to be redrawn on screen // Also avoIDs SceneKit rendering freeze dispatch_async(dispatch_get_main_queue()) { // Get your screenshot the simple way let screenshot = scnVIEw.snapshot() // Or use your function // let screenshot = self.turnVIEwToImage(scnVIEw,afterUpdates: true) // Then save the screenshot,or do whatever you want let urlPath = NSURL(fileURLWithPath: NSSearchPathForDirectorIEsInDomains(.documentDirectory,.UserDomainMask,true).first!).URLByAppendingPathComponent("Image.png") try! UIImagePNGRepresentation(screenshot)!.writetoURL(urlPath,options: .AtomicWrite) } }} 这个委托方法对我们来说并不完美,因为即使渲染了场景,它还没有准备好在屏幕上重绘视图,因为这种委托方法让我们有机会进行任何我们想要的自定义渲染.此外,如果您尝试在此处调用drawVIEwHIErarchyInRect:afterScreenUpdates:或snapshot,则SceneKit渲染将完全停止(在模拟器和iOS 9.3设备上),这可能是SceneKit错误.对于委托方法,我们没有更好的选择,但我的解决方案是在主队列上调度异步调用,该主队列将在SceneKit渲染循环完全完成后运行,并且渲染的图像可以在屏幕上重绘.如果使用drawVIEwHIErarchyInRect:afterScreenUpdates:,请确保afterScreenUpdates设置为true,因为此时似乎尚未执行实际绘图.并且我确定你知道,确保异步调用在主线程上运行,因为永远不应该从另一个线程触及UIKit对象.
顺便说一句,我复制了你的问题,并使用Xcode 7.3(带有旋转船的那个)提供的默认SceneKit项目模板找到了我的解决方案.每次点击场景视图时,我都会切换船的隐藏属性,然后设置标记以捕获屏幕截图.如果需要,我们可以使用此模板作为进一步讨论的基础.
总结以上是内存溢出为你收集整理的ios – 使用隐藏的SCNNode捕获SCNView的图像/屏幕截图:在屏幕更新后不能正常工作的drawViewHierarchyInRect全部内容,希望文章能够帮你解决ios – 使用隐藏的SCNNode捕获SCNView的图像/屏幕截图:在屏幕更新后不能正常工作的drawViewHierarchyInRect所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)