ARKit:如何在ARKit场景中添加UIView?

时间:2018-02-09 07:43:26

标签: ios iphone swift uiview arkit

我正在使用ARKit开展AR项目。

我想在ARKit场景中添加一个UIView。当我点击一个对象时,我希望获得一个" pop-up"在对象旁边。这些信息在UIView中。

是否可以将此UIView添加到ARKit场景? 我将这个UIView设置为场景,然后我该怎么办? 我可以给它一个节点然后将它添加到ARKit场景吗?如果是这样,它是如何工作的?

还是有另一种方式吗?

谢谢!

编辑:我的SecondViewController的代码

class InformationViewController: UIViewController {

    @IBOutlet weak var secondView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view = secondView
    }
}

编辑2:firstViewController中的代码

guard let secondViewController = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {
    print ("No secondController")
    return
}

let plane = SCNPlane(width: CGFloat(0.1), height: CGFloat(0.1))       
plane.firstMaterial?.diffuse.contents = secondViewController.view

let node = SCNNode(geometry: plane)

我只得到一架飞机的白色屏幕,而不是视线。

3 个答案:

答案 0 :(得分:14)

实现这一目标的最简单(尽管未记录)方法是将视图控制器支持的UIView设置为SCNPlane(或任何其他几何体上的材质的漫反射内容),但它有效最好的飞机,原因很明显)。

let plane = SCNPlane()
plane.firstMaterial?.diffuse.contents = someViewController.view
let planeNode = SCNNode(geometry: plane)

您必须将视图控制器保留在某处,否则它将被释放并且平面将不可见。仅使用UIView而不使用任何UIViewController会产生错误。

关于它的最好的事情是它保持所有的手势,实际上只是作为一个简单的视图。例如,如果您使用UITableViewController的视图,则可以在场景中向右滚动。

我还没有在iOS 10及更低版本上测试它,但到目前为止它一直在iOS 11上运行。适用于普通的SceneKit场景和ARKit。

答案 1 :(得分:2)

我现在无法为您提供代码,但这是如何做到的。

  1. 创建SCNPlane
  2. 使用您需要的所有元素创建UIView
  3. UIView创建图像上下文。
  4. 将此图片用作SCNPlane
  5. 的素材

    或者更轻松地使用标签制作SKScene并将其添加为SCNPlane的素材。

答案 2 :(得分:1)

要将文字放置在世界标签中,请将其绘制到图像中,然后将该图像附加到SCNNode

例如:

let text = "Hello, Stack Overflow."
let font = UIFont(name: "Arial", size: CGFloat(size))
let width = 128
let height = 128

let fontAttrs: [NSAttributedStringKey: Any] = 
[NSAttributedStringKey.font: font as UIFont]

let stringSize = self.text.size(withAttributes: fontAttrs)
let rect = CGRect(x: CGFloat((width / 2.0) - (stringSize.width/2.0)),
                  y: CGFloat((height / 2.0) - (stringSize.height/2.0)),
                  width: CGFloat(stringSize.width),
                  height: CGFloat(stringSize.height))

let renderer = UIGraphicsImageRenderer(size: CGSize(width: CGFloat(width), height: CGFloat(height)))
let image = renderer.image { context in

    let color = UIColor.blue.withAlphaComponent(CGFloat(0.5))

    color.setFill()
    context.fill(rect)

    text.draw(with: rect, options: .usesLineFragmentOrigin, attributes: fontAttrs, context: nil)
}

let plane = SCNPlane(width: CGFloat(0.1), height: CGFloat(0.1))
plane.firstMaterial?.diffuse.contents = image

let node = SCNNode(geometry: plane)

编辑: 我添加了这些内容:

let color = UIColor.blue.withAlphaComponent(CGFloat(0.5))

color.setFill()
context.fill(rect)

这可让您设置背景颜色和不透明度。还有其他方法可以做到这一点 - 这也可以让你绘制复杂的形状 - 但这对于基本颜色来说是最简单的。

编辑2:添加了对stringSizerect

的引用