ios – 使用隐藏的SCNNode捕获SCNView的图像屏幕截图:在屏幕更新后不能正常工作的drawViewHierarchyInRect

ios – 使用隐藏的SCNNode捕获SCNView的图像屏幕截图:在屏幕更新后不能正常工作的drawViewHierarchyInRect,第1张

概述下面的代码捕获了SCNView1的屏幕截图,但它并没有完全正常工作. SCNView1包含Node1.目标是在没有Node1的情况下捕获SCNView1. 但是,将afterScreenUpdates设置为true(或false)无效:屏幕截图包含Node1,无论如何. 有什么问题? Node1.hidden = truelet screenshot = turnViewToImage(SCNV 下面的代码捕获了SCNVIEw1的屏幕截图,但它并没有完全正常工作.

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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1105432.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-28
下一篇2022-05-28

发表评论

登录后才能评论

评论列表(0条)

    保存