将NSClickGestureRecognizer改为NSPan后SceneKit相机旋转失效
macOS SceneKit替换NSPan手势后相机旋转失效的解决办法
为啥会失效?
原来的NSClickGestureRecognizer是点击触发的手势,而NSPanGestureRecognizer是拖动手势,两者的触发逻辑、回调传递的数据完全不一样。原模板里的handleClick方法只适配了点击场景的逻辑,直接替换手势类型后,代码根本没法处理拖拽位移来驱动相机旋转。
怎么改才能用?
- 先修正手势初始化代码(你已经完成这一步,顺便把方法名改得更贴合场景):
let panGesture = NSPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
- 重写手势处理方法,适配拖拽逻辑:
@objc func handlePan(_ gestureRecognizer: NSPanGestureRecognizer) { guard let scnView = gestureRecognizer.view as? SCNView else { return } guard let cameraNode = scnView.scene?.rootNode.childNode(withName: "camera", recursively: true) else { return } // 获取拖拽的位移数据 let translation = gestureRecognizer.translation(in: scnView) // 调整系数可以控制旋转灵敏度,自己试个顺手的数值 let xRotate = Float(translation.y) * 0.01 let yRotate = Float(-translation.x) * 0.01 switch gestureRecognizer.state { case .changed: // 拖拽过程中实时更新相机旋转角度 cameraNode.eulerAngles.x += xRotate cameraNode.eulerAngles.y += yRotate case .ended: // 想加惯性效果的话,这里可以用velocity计算后续动画,可选 let dragSpeed = gestureRecognizer.velocity(in: scnView) // 比如添加短动画让相机平滑减速停下 default: break } }
- 可选优化:避免相机轴向锁定
如果旋转到特定角度出现卡顿或视角锁死,把相机放到父节点里,旋转父节点即可:
// 初始化相机时调整结构 let cameraParent = SCNNode() cameraParent.addChildNode(cameraNode) scnView.scene?.rootNode.addChildNode(cameraParent) // 然后在handlePan里修改父节点的旋转 cameraParent.eulerAngles.x += xRotate cameraParent.eulerAngles.y += yRotate
核心差异说明:
- 点击手势只会在点击完成时触发一次,拖动手势会在拖拽开始、持续、结束等多个阶段触发回调
- 拖拽手势需要通过
translation(in:)获取位移,靠state判断当前拖拽阶段,才能实现实时的相机旋转跟踪
内容的提问来源于stack exchange,提问作者bhartsb
相关产品推荐
相关产品推荐

