我已经实现了缩放功能,但是我用来移动玩家的节点,指向玩家移动方向的箭头,保持相同的大小,我无法弄清楚如何按比例缩放它们,所以如果我放大,按钮变小并靠近播放器以留在屏幕上,反之亦然当你缩小时。
这是我写的允许缩放的代码:
@objc func handlePinch(sender: UIPinchGestureRecognizer) {
guard sender.view != nil else { return }
if sender.state == .began || sender.state == .changed {
sender.view?.transform = (sender.view?.transform.scaledBy(x: sender.scale, y: sender.scale))!
sender.scale = 1.0
}
}
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(sender:)))
view.addGestureRecognizer(pinch)
你在使用 SpriteKit 吗?
如果是这样,您可能可以在相机节点比例上工作以实现“缩放”功能:https://developer.apple.com/documentation/spritekit/skcameranode/getting_started_with_a_camera
@objc func handlePinch(sender: UIPinchGestureRecognizer) {
guard sender.view != nil else {
return
}
if sender.state == .began || sender.state == .changed {
self.camera.xScale = sender.scale
self.camera.yScale = sender.scale
}
}
Apple 的文档说:
因为相机是一个节点,所以您可以像定义任何其他节点一样在场景中定义它的位置。动作、物理和 GameplayKit 行为也可以应用于相机节点。使用相机节点渲染场景时,会发生以下情况: 渲染场景,使相机节点的原点位于场景的中间。 相机节点的 xScale、yScale 和 zRotation 属性的反转应用于场景中的所有节点。
你可能应该反转发件人比例值:
self.camera.xScale = -sender.scale
工作解决方案:
@objc func handlePinch(_ sender: UIPinchGestureRecognizer) {
guard let camera = self.camera else {
return
}
if sender.state == .began {
sender.scale = camera.xScale
}
if sender.state == .changed {
camera.setScale(sender.scale)
}
}
为清楚起见,
self.camera
是 SKScene 上定义的弱 var 属性。
当发起捏合手势时,sender 的比例总是从 1.0 开始。所以如果你想让你的相机从它以前的比例开始,你需要set the sender's scale to your previous camera scale.
例如,如果手势结束时相机的比例为 1.5,则下一次捏合手势开始时,发送者的比例设置为 1.5。然后当手指移动时(即
sender.state == .changed
),发送者的比例从1.5开始增加/减少。
否则,相机的比例会设置回 1.0,导致裁剪效果。您将无法放大/缩小超过一定数量,因为比例总是从 1.0 开始,而不是从停止的地方开始。
根据 Apple 的文档,
因为你的动作方法可能会被调用很多次,所以你不能简单地将当前的比例因子应用到你的内容上。 (...) 相反,缓存您内容的原始值,将比例因子应用于该原始值,然后将新值应用回您的内容。
这意味着只要手指移动(即
sender.state == .changed)
),就会连续(每秒多次)调用连接到手势识别器的动作方法。如果您直接对相机应用任何类型的缩放,无论是加法、乘法、除法例如camera.setScale(sender.scale + 0.1)
,相机的比例将呈指数变化。
您可以在这里阅读更多内容 - https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_uikit_gestures/handling_pinch_gestures
我的原始答案没有说明
SKCameraNode
将其逆比例缩放应用于场景元素的事实。也就是说,对于期望缩小相机的捏合手势,相机实际上是在放大。如果你想让相机按预期放大和缩小,可以使用以下代码:
在
GameScene.swift
中,添加一个变量来存储之前的相机比例:
class GameScene: SKScene {
var previousCameraScale: CGFloat = CGFloat.zero
}
改变
handlePinch
功能如下:
@objc func handlePinch(_ sender: UIPinchGestureRecognizer) {
guard let camera = self.camera else {
return
}
if sender.state == .began {
previousCameraScale = camera.xScale
sender.scale = previousCameraScale
}
if sender.state == .changed {
let change = sender.scale - previousCameraScale
let newScale = max(min((previousCameraScale - change), maxCameraScale), minCameraScale)
camera.setScale(newScale)
}
}
对于
sender.state == .began
,没有变化。发送者的比例仍然设置为之前的相机比例,因此没有裁剪效果,只是现在我们将变量存储在 previousCameraScale
属性中,以便我们可以在重复调用 handlePinch
动作方法时使用它。
对于sender.state == .changed
,我们首先计算发送者的尺度改变了多少。然后我们从之前的相机比例中减去这个变化,最后将相机的比例设置为这个新的比例。
例如,如果
previousCameraScale
= 1.5 并且用户放大(手指张开,导致 sender.scale
增加,比如说,1.7),则 change
将为 0.2。相机的比例需要随着发送方比例的增加而减小。所以如果 sender.scale
增加到 1.7,camera.scale
需要减少到 1.3。这本质上就是previousCameraScale - change
的意思。
我还将
newScale
夹在下限和上限之间,以便 (1) 比例不会变为负数,这会翻转所有内容,并且 (2) 相机的比例不会变得太大,在这种情况下,一切都会变得超小