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