简体   繁体   中英

How to use SwiftUI and SceneKit together?

I have a SCNCylinder displayed in a scene inside a frame in SwiftUI. I want to rotate it by 180º around some axis. I want the cylinder to rotate after I press the 180º (kind of) button in the SwiftUI view. Currently I am able to rotate it once but it does not rotate the second time I press the button. I tried defining the the rotation angle first to zero and then to 180º but after doing this the whole thing just crashes after I press the button. I just want the cylinder to rotate the second time after I press the button.

Here is my code:

//SwiftUI view

struct ContentView: View {
@State var rotationAngle: Angle = .degrees(0)
var body: some View {

    VStack{

        Text("180º").onTapGesture {
           self.rotationAngle = .zero
           self.rotationAngle = .degrees(180)

        }

        }
        SceneKitView(radius: 0.02, height: 2, angle: $rotationAngle)
            .position(x: 200.0, y: 140)
            .frame(width: 300, height: 300, alignment: .center)
        }

     }

  }

//SceneKit View

 struct SceneKitView: UIViewRepresentable {

  @Binding var angle: Angle

 let cylindernode: SCNNode

 init(radius: CGFloat, height: CGFloat, angle: Binding<Angle>) {

    let cylinder = SCNCylinder(radius: radius, height: height)
    cylinder.firstMaterial?.diffuse.contents = UIColor.green
    self.cylindernode = SCNNode(geometry: cylinder)
    self.cylindernode.position = SCNVector3(0, 0, 0)
    self.cylindernode.orientation = SCNVector4(0, 0, 0, 0)
    cylindernode.pivot = SCNMatrix4MakeTranslation(0, -1, 0)

    self._angle = angle

}

//SCNScene

func makeUIView(context: UIViewRepresentableContext<SceneKitView>) -> SCNView {

    let sceneView = SCNView()
    sceneView.scene = SCNScene()
    sceneView.autoenablesDefaultLighting = true
    sceneView.allowsCameraControl = true
    sceneView.scene?.rootNode.addChildNode(cylindernode)
    return sceneView
}

func updateUIView(_ sceneView: SCNView, context: UIViewRepresentableContext<SceneKitView>) {

 //Rotation animation

    let rotation = CABasicAnimation(keyPath: "transform.rotation")
    rotation.isRemovedOnCompletion = false
    rotation.duration = 5
    cylindernode.addAnimation(rotation, forKey: "rotation")
    cylindernode.rotation = SCNVector4(1, 0, 0, angle.radians)

}

}

}

After I remove the line self.rotationAngle = .zero the code runs well but the view does not update. But if I keep the line the whole thing just crashes after I press the button.

try this: But because of the lot of questions you ask and they are so basic, maybe you should check for some beginner swift courses to learn how to set variables...and this has nothing to do with Scenekit and SwiftUI - it is just changing a variable.

struct ContentView: View {
    @State var rotationAngle: Angle = .degrees(0)
    var body: some View {

        VStack{

            Text("180º").onTapGesture {
                self.rotationAngle += .degrees(90)
                print(self.rotationAngle)
            }
            SceneKitView(radius: 0.02, height: 2, angle: $rotationAngle)
                .position(x: 200.0, y: 140)
                .frame(width: 300, height: 300, alignment: .center)
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM