Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift向SCNNode添加按钮_Swift_Xcode_Scenekit_Arkit_Xcode9 Beta - Fatal编程技术网

Swift向SCNNode添加按钮

Swift向SCNNode添加按钮,swift,xcode,scenekit,arkit,xcode9-beta,Swift,Xcode,Scenekit,Arkit,Xcode9 Beta,我在玩ARKit和图像检测。 现在我有了一个应用程序,可以检测图像,并将飞机放在屏幕上检测到的物体所在的位置 如何在平面上添加按钮之类的可单击元素。我希望在每个检测到的对象上都有一个单击事件 这是我的渲染器函数的外观: func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let imageAnchor = anchor as? ARImage

我在玩ARKit和图像检测。 现在我有了一个应用程序,可以检测图像,并将飞机放在屏幕上检测到的物体所在的位置

如何在平面上添加按钮之类的可单击元素。我希望在每个检测到的对象上都有一个单击事件

这是我的渲染器函数的外观:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        let referenceImage = imageAnchor.referenceImage
        updateQueue.async {
            let plane = SCNPlane(width: referenceImage.physicalSize.width,
                                 height: referenceImage.physicalSize.height)
            let planeNode = SCNNode(geometry: plane)

            planeNode.opacity = 0.25
            planeNode.eulerAngles.x = -.pi / 2
            planeNode.runAction(self.imageHighlightAction)
            node.addChildNode(planeNode)
        }

        DispatchQueue.main.async {
            let imageName = referenceImage.name ?? ""
            self.statusViewController.cancelAllScheduledMessages()
            // self.statusViewController.showMessage("Detected image “\(imageName)”")
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let second = storyboard.instantiateViewController(withIdentifier: "InfoViewController")as! InfoViewController
            second.myStringValue = imageName
            // self.navigationController?.pushViewController(second, animated: true)
        }
    }

有几种方法可以实现这一点:

1:标准方法

在您的
delegate
方法中,为每个节点指定一个名称,如下所示(显然,如果您有许多节点,您希望根据需要将它们存储在数组或字典中):

然后使用
触摸开始
,执行hitTest并相应地处理您的触摸:

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    /*
     1. Get The Current Touch Location
     2. Check That We Have Touched A Valid Node
     3. Check If The Node Has A Name
     4. Handle The Touch
     */

    guard let touchLocation = touches.first?.location(in: augmentedRealityView),
        let hitNode = augmentedRealityView?.hitTest(touchLocation, options: nil).first?.node,
        let nodeName = hitNode.name
        else {
            //No Node Has Been Tapped
            return

    }
    //Handle Event Here e.g. PerformSegue
    print(nodeName)

}
在委托方法中,执行以下操作:

  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    //1. Check We Have The Image Anchor
    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    //2. Get The Reference Image
    let referenceImage = imageAnchor.referenceImage

    //1. Create The Plane Geometry With Our Width & Height Parameters
    let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)

    //2. Create A New Material
    let material = SCNMaterial()

    DispatchQueue.main.async {
        //3. Create The New Clickable View
        let clickableElement = ClickableView(frame: CGRect(x: 0, y: 0,
                                                           width: 300,
                                                           height: 300))
        clickableElement.tag = 1

        //4. Add The Clickable View As A Materil
        material.diffuse.contents = clickableElement
    }

    //5. Create The Plane Node
    let planeNode = SCNNode(geometry: planeGeometry)

    planeNode.geometry?.firstMaterial = material

    planeNode.opacity = 0.25

    planeNode.eulerAngles.x = -.pi / 2

    //6. Add It To The Scene
    node.addChildNode(planeNode)
}

这会让你开始…

谢谢!这对我帮助很大。第二种方法非常好。对于任何试图实现此功能并希望通过“显示/推送”导航到其他屏幕的人,请注意,SceneKit会为分配给材质的每个此类UIKit元素创建新的
UIWindow
对象,这就是它发送要处理的事件的方式。因此,请注意进行必要的清理以避免不必要的行为(例如,您可以迭代
UIApplication.shared.windows
并隐藏非关键的窗口)。
/// Clickable View
class ClickableView: UIButton{

    override init(frame: CGRect) {

    super.init(frame: frame)

    self.addTarget(self, action:  #selector(objectTapped(_:)), for: .touchUpInside)

    self.backgroundColor = .red

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

/// Detects Which Object Was Tapped
///
/// - Parameter sender: UIButton
@objc func objectTapped(_ sender: UIButton){

    print("Object With Tag \(tag)")

   }

}
  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    //1. Check We Have The Image Anchor
    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    //2. Get The Reference Image
    let referenceImage = imageAnchor.referenceImage

    //1. Create The Plane Geometry With Our Width & Height Parameters
    let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)

    //2. Create A New Material
    let material = SCNMaterial()

    DispatchQueue.main.async {
        //3. Create The New Clickable View
        let clickableElement = ClickableView(frame: CGRect(x: 0, y: 0,
                                                           width: 300,
                                                           height: 300))
        clickableElement.tag = 1

        //4. Add The Clickable View As A Materil
        material.diffuse.contents = clickableElement
    }

    //5. Create The Plane Node
    let planeNode = SCNNode(geometry: planeGeometry)

    planeNode.geometry?.firstMaterial = material

    planeNode.opacity = 0.25

    planeNode.eulerAngles.x = -.pi / 2

    //6. Add It To The Scene
    node.addChildNode(planeNode)
}