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

olqngx59  于 2023-04-19  发布在  Swift
关注(0)|答案(2)|浏览(190)

我实现了一个缩放功能,但是我用来移动播放器的节点,指向播放器移动方向的箭头,保持相同的大小,我不知道如何按比例缩放它们,所以如果我放大,按钮会变小并移动到更靠近播放器的位置以保持在屏幕上,反之亦然。
下面是我写的允许缩放的代码:

@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)
ffscu2ro

ffscu2ro1#

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

ar7v8xwq

ar7v8xwq2#

工作溶液:

@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属性。
当开始捏手势时,发送者的比例始终从1.0开始。因此,如果您希望您的相机从之前的比例开始,则需要将发送者的比例设置为您的之前的相机比例
例如,如果手势结束时相机的缩放比例为1.5,则下次开始捏手势时,发送者的缩放比例将设置为1.5。然后,当移动手指(即sender.state == .changed)时,发送者的缩放比例将从1.5开始增加/减少。
否则,相机的比例会被设置回1.0,导致剪切效果。您将无法放大/缩小超过一定量,因为比例总是从1.0开始,而不是从停止的地方开始。
根据苹果的文档
因为您的action方法可能会被多次调用,所以您不能简单地将当前的比例因子应用于内容。(...)相反,缓存内容的原始值,将比例因子应用于原始值,然后将新值应用回内容。
相机的比例可以方便地缓存,存储在xScaleyScale属性中。
你可以在这里阅读更多-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)相机的比例不会变得太大,在这种情况下,所有内容都将变得非常小。

相关问题