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

Zheoni picture Zheoni · Oct 11, 2019 · Viewed 11.4k times · Source

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?

Answer

James picture James · Oct 19, 2019

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

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
}.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.