Home > Software engineering >  Proportionally scaling UIPanGesture actions to zoom level in a SpriteKit scene
Proportionally scaling UIPanGesture actions to zoom level in a SpriteKit scene

Time:02-14

I have a SpriteKit scene in my iOS app that makes use of both pan and pinch gestures - panning for moving the view of the scene's camera, and and pinch gestures for zooming in and out of the scene by scaling the scene's camera.

Zooming works well:

@objc func pinchGestureAction(_ sender: UIPinchGestureRecognizer) {

    guard let camera = canvasScene.camera else {
        return
    }

    if sender.state == .began {
        previousCameraScale = camera.xScale
    } else if sender.state == .ended {
        previousCameraScale = camera.xScale
        return
    }

    camera.setScale(previousCameraScale * 1 / sender.scale)

    print(camera.xScale)
    print(camera.yScale)
}

The issue is with the panning, which is done using the pan gesture recognizer:

@objc func panGestureAction(_ sender: UIPanGestureRecognizer) {

    if sender.state != .changed {
       return
    }

    guard let camera = canvasScene.camera else {
       return
    }

    // Get touch delta
    let translation = sender.translation(in: sender.view!) 

    // Move camera
    self.canvasScene.camera?.position.x -= translation.x
    self.canvasScene.camera?.position.y  = translation.y

    // Reset
    sender.setTranslation(CGPoint.zero, in: sender.view)
}

Panning works pretty well when the user is zoomed in really close to the objects on the canvas. When the camera is zoomed further out, it takes a considerably large amount of gestures to pan through the canvas scene than it did when the camera view was zoomed in at a closer view.

I tried scaling the values of the camera position by that of the camera's scaling factor like so:

self.canvasScene.camera?.position.x -= translation.x * camera.xScale
self.canvasScene.camera?.position.y  = translation.y * camera.yScale

But that does not seem to work. Any ideas on how to best implement proper camera panning behavior based on that of how far a camera is zoomed in to a scene?

CodePudding user response:

To get the desired behavior, I had to apply an additional scaling factor to the SKScene's camera position:

@objc func panGestureAction(_ sender: UIPanGestureRecognizer) {
    if sender.state != .changed {
        return
    }
    
    guard let camera = canvasScene.camera else {
        return
    }
    
    // Get touch delta
    let translation = sender.translation(in: sender.view!)
    
    // Move camera
    self.canvasScene.camera?.position.x -= translation.x * camera.xScale / 1.5
    self.canvasScene.camera?.position.y  = translation.y * camera.yScale / 1.5
    
    // Reset
    sender.setTranslation(CGPoint.zero, in: sender.view)
}
  • Related