放大或缩小时如何缩放 SKNodes?

问题描述 投票:0回答:2

我已经实现了缩放功能,但是我用来移动玩家的节点,指向玩家移动方向的箭头,保持相同的大小,我无法弄清楚如何按比例缩放它们,所以如果我放大,按钮变小并靠近播放器以留在屏幕上,反之亦然当你缩小时。

这是我写的允许缩放的代码:

@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)
swift sprite-kit zooming sknode
2个回答
1
投票

你在使用 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


0
投票

工作解决方案:

@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) 相机的比例不会变得太大,在这种情况下,一切都会变得超小

© www.soinside.com 2019 - 2024. All rights reserved.