swiftimagescrollviewswiftuipinchzoom

Isn't there an easy way to pinch to zoom in an image in SwiftUI?


I want to be able to resize and move an image in SwiftUI (like if it were a map) with pinch to zoom and drag it around.

With UIKit I embedded the image into a UIScrollView and it took care of it, but I don't know how to do it in SwiftUI. I tried using MagnificationGesture but I cannot get it to work smoothly.

I've been searching about this for a while, does anyone know if there's an easier way?


Solution

  • The SwiftUI API is pretty unhelpful here: the onChanged gives number relative to start of current zoom gesture and no obvious way within a callback to get the initial value. And there is an onEnded callback but easy to miss/forget.

    A work around, add:

    @State var lastScaleValue: CGFloat = 1.0
    @State private var scale: CGFloat = 1.0
    

    Then in the callback:

    .gesture(
        MagnificationGesture()
            .onChanged { val in
                let delta = val / self.lastScaleValue
                self.lastScaleValue = val
                let newScale = self.scale * delta
    
                //... anything else e.g. clamping the newScale
                self.scale = newScale
            }.onEnded { val in
                // without this the next gesture will be broken
                self.lastScaleValue = 1.0
            }
    )
    

    where newScale is your own tracking of scale (perhaps state or a binding). If you set your scale directly it will get messed up as on each tick the amount will be relative to previous amount.