I want to pinch zoom an image on a view.
I have this code:
@State var progressingScale: CGFloat = 1
var body: some View {
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fit)
.padding([.leading, .trailing], 20)
.scaleEffect(progressingScale)
.gesture(MagnificationGesture()
.onChanged { value in
progressingScale = value.magnitude
}
.onEnded {value in
progressingScale = value.magnitude
}
)
}
This code works relatively well but suppose I scale the image up and lift the fingers. Now the image is huge.
Then, I try to pinch and scale it up more. The image goes back to scale = 1
and starts scaling up again. I want it to start at the scale it was when the fingers were released the first time.
Cannot figure why... any ideas?
In order for the magnification to stick, you need to keep track of two values: the image's permanent scale (imageScale
) and the current magnification value (magnifyBy
). The scale applied to the image is the product of these two values (imageScale * magnifyBy
).
While the MagnificationGesture
is in progress, just change the magnifyBy
property. When the gesture ends, permanently apply the magnification to the imageScale
and set magnifyBy
back to 1
.
struct ContentView: View {
@State private var imageScale: CGFloat = 1
@State private var magnifyBy: CGFloat = 1
var body: some View {
Image(systemName: "globe")
.resizable()
.aspectRatio(contentMode: .fit)
.padding([.leading, .trailing], 20)
.scaleEffect(imageScale * magnifyBy)
.gesture(MagnificationGesture()
.onChanged { value in
magnifyBy = value.magnitude
}
.onEnded {value in
imageScale *= value.magnitude
magnifyBy = 1
}
)
}
}