SwiftUI + 场景套件 + 组合 + 几何阅读器 ==> 可滚动的 3D 模型列表 + 通过滚动列表旋转 3D 模型



我想创建一个3D型号的可滚动列表(这里:Xcode的默认船舶模型,您可以在xcode的 Game> Game> Game> game project中找到(。p>为此我创建了3 view 结构:

  • 一个用于查看3D模型(称为 SceneKitView (
  • 一个用于cardView(称为 mycardview (
  • 一个适用于3D模型的可滚动列表(称为mycardslistview(

这是结构:

SceneEkitView (顺便说一句,我添加了Xcode的默认 game project的 art.scnassets project project

import SwiftUI
import SceneKit
struct ScenekitView : UIViewRepresentable {
    @Binding var yRotation : Float
    let scene = SCNScene(named: "art.scnassets/ship.scn")!
    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)
        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)
        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)
        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
        // animate the 3d object
        ship.eulerAngles = SCNVector3(x: 0, y: self.yRotation * Float((Double.pi)/180.0) , z: 0)
        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }
    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene
        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true
        // show statistics such as fps and timing information
        scnView.showsStatistics = true
        // configure the view
        scnView.backgroundColor = UIColor.black
    }
}
#if DEBUG
struct ScenekitView_Previews : PreviewProvider {
    static var previews: some View {
        ScenekitView(yRotation: .constant(0))
    }
}
#endif

myCardView

import SwiftUI
struct MyCardView : View {
    @Binding var yRotation: Float
    var body: some View {
        VStack(spacing: 0) {
            ZStack {
                Rectangle()
                    .foregroundColor(.black)
                    .opacity(0.8)
                    .frame(width:250, height: 70)
                Text( "Ship ( self.yRotation )" )
                    .foregroundColor(.white)
                    .font(.title)
                    .fontWeight(.bold)
            }
            ScenekitView(yRotation: self.$yRotation )
                .frame(width: 250, height: 250)
        }
        .cornerRadius(35)
        .frame(width: 250,height: 320)
    }
}
#if DEBUG
struct MyCardView_Previews : PreviewProvider {
    static var previews: some View {
        MyCardView(yRotation: .constant(90))
    }
}
#endif

mycardslistview

import SwiftUI
struct MyCardsListView: View {
    @State var yRotation: Float = 0
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(0...2) { number in
                    GeometryReader { geometry in
                        MyCardView(yRotation: self.$yRotation )
                        .rotation3DEffect(Angle(degrees: Double(geometry.frame(in: .global).minX) / -20), axis: (x: 0, y: 10, z: 0))
                    }
                    .padding()
                    .frame(width: 250, height: 350)
                }
            }
        }
    }
}
#if DEBUG
struct Product3DView_Previews: PreviewProvider {
    static var previews: some View {
        MyCardsListView()
    }
}
#endif

in mycardslistview 我正在使用GeometryReader

获得每张卡的最小X位置

我的目标是:

当我在 mycardslistview 中滚动 cards 时,每个船舶型号都应相对于旋转其卡的最小x位置(所有它们不应同时以相同的旋转角度旋转(

(我知道我可能会在使用绑定,状态等方面犯很多错误,对此感到抱歉(

您的代码中有很多问题:

  1. 您永远不会为yRotation分配一个值。
  2. 您在MyCardsListView中只有一个yRotation变量,但是由于您想具有不同的旋转值,具体取决于视图的位置,因此每个视图都需要一个yRotation变量。
  3. 以下行:
ship.eulerAngles = SCNVector3(x: 0, y: self.yRotation * Float((Double.pi)/180.0) , z: 0)

makeUIView()方法内部,但是该方法仅执行一次(创建视图时(。您希望值继续更新,因此您应该在updateUIView()中分配值。

您绝对应该观看WWDC会话 226:SwiftUi 231中的数据流:集成SwiftUi

相关内容

  • 没有找到相关文章