我想创建一个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
我的目标是:
当我在 mycardslistview 中滚动 cards 时,每个船舶型号都应相对于旋转其卡的最小x位置(所有它们不应同时以相同的旋转角度旋转(
(我知道我可能会在使用绑定,状态等方面犯很多错误,对此感到抱歉(
您的代码中有很多问题:
- 您永远不会为
yRotation
分配一个值。 - 您在
MyCardsListView
中只有一个yRotation
变量,但是由于您想具有不同的旋转值,具体取决于视图的位置,因此每个视图都需要一个yRotation
变量。 - 以下行:
ship.eulerAngles = SCNVector3(x: 0, y: self.yRotation * Float((Double.pi)/180.0) , z: 0)
在makeUIView()
方法内部,但是该方法仅执行一次(创建视图时(。您希望值继续更新,因此您应该在updateUIView()
中分配值。
您绝对应该观看WWDC会话 226:SwiftUi 和 231中的数据流:集成SwiftUi 。