You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让移出屏幕的SceneKit节点重新居中显示

SwiftUI + SceneKit Mac应用重置节点居中实现

核心思路

根据你的场景分两种情况处理:

  • 如果是默认相机控制(allowsCameraControl = true):Magic Mouse手势移动的是相机,节点仍在初始位置,只需重置相机朝向和位置,让节点回到视野中心。
  • 如果是自定义手势移动节点:需要保留节点的旋转、缩放属性,仅重置节点位置到初始的(0,0,0)。

实现代码

1. 封装SceneKit视图(适配MacOS)

通过NSViewRepresentable包装SCNView,同时提供重置逻辑:

import SwiftUI
import SceneKit

struct SceneKitView: NSViewRepresentable {
    @Binding var triggerReset: Bool
    // 存储场景核心元素引用
    private var cubeNode: SCNNode!
    private var cameraNode: SCNNode!

    func makeNSView(context: Context) -> SCNView {
        let scnView = SCNView()
        scnView.allowsCameraControl = true // 默认相机控制,若你自定义了节点手势可设为false
        
        // 初始化场景
        let scene = SCNScene()
        scnView.scene = scene
        
        // 创建立方体节点
        let cubeGeo = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
        cubeNode = SCNNode(geometry: cubeGeo)
        cubeNode.position = .zero
        scene.rootNode.addChildNode(cubeNode)
        
        // 创建相机
        cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(0, 0, 5)
        cameraNode.look(at: .zero)
        scene.rootNode.addChildNode(cameraNode)
        
        // 添加灯光
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light?.type = .omni
        lightNode.position = SCNVector3(5, 5, 5)
        scene.rootNode.addChildNode(lightNode)
        
        return scnView
    }

    func updateNSView(_ nsView: SCNView, context: Context) {
        guard triggerReset else { return }
        
        // 根据你的场景选择以下一种重置逻辑
        
        // 逻辑1:重置相机(适用于默认相机控制场景)
        cameraNode.position = SCNVector3(0, 0, 5)
        cameraNode.look(at: cubeNode.position) // 始终看向立方体
        
        // 逻辑2:重置节点位置(适用于自定义手势移动节点的场景)
        // let savedRotation = cubeNode.eulerAngles
        // let savedScale = cubeNode.scale
        // cubeNode.position = .zero
        // cubeNode.eulerAngles = savedRotation
        // cubeNode.scale = savedScale
        
        // 重置触发标记
        triggerReset = false
    }
}

2. SwiftUI主视图(含重置按钮)

struct ContentView: View {
    @State private var resetTrigger = false

    var body: some View {
        VStack {
            SceneKitView(triggerReset: $resetTrigger)
                .frame(minWidth: 600, minHeight: 400)
            
            Button("重置居中") {
                resetTrigger = true
            }
            .padding()
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}

注意事项

  • 若你使用了自定义手势移动节点,注释掉逻辑1,启用逻辑2即可。
  • look(at:)方法会确保相机始终指向立方体,即使节点位置有变动(如果是自定义节点移动场景)。
  • 代码中保留了节点的旋转和缩放属性,完全符合你“不改变已应用变换”的要求。

内容的提问来源于stack exchange,提问作者Lowell Bahner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:45:03