I want to allow the user to pinch-to-zoom in on an Image in SwiftUI. I figured the best way to go was to use a MagnificationGesture
and, following along with the answer here, I ended up with this code:
// outside of `var body: some View`
@State private var scale: Int = 1.0
@State private var lastScale: Int = 1.0
// Image
Image("dog")
.resizable()
.aspectRatio(contentMode: .fit)
.gesture(MagnificationGesture()
.onChanged { val in
let delta = val / self.lastScale
self.lastScale = val
let newScale = self.scale * delta
self.scale = newScale
}
.onEnded { _ in
self.lastScale = 1.0
}
)
.scaleEffect(scale)
This code handles magnification fine, but does not let the user zoom in on a specific area. Instead, it always zooms in on the middle of the image.
How would I go about handling pinch-to-zoom behavior on an image in SwiftUI?
Thanks in advance!
The code creates a pinch-to-zoom effect by adding a drag gesture in addition to the magnification gesture. Use of viewState allows a changing offset position when using the drag gesture.
struct ContentView: View {
@State private var scale: CGFloat = 1.0
@State private var lastScale: CGFloat = 1.0
@State private var viewState = CGSize.zero
var body: some View {
Image("dog")
.resizable()
.aspectRatio(contentMode: .fit)
.animation(.spring())
.offset(x: viewState.width, y: viewState.height)
.gesture(DragGesture()
.onChanged { val in
self.viewState = val.translation
}
)
.gesture(MagnificationGesture()
.onChanged { val in
let delta = val / self.lastScale
self.lastScale = val
if delta > 0.94 { // if statement to minimize jitter
let newScale = self.scale * delta
self.scale = newScale
}
}
.onEnded { _ in
self.lastScale = 1.0
}
)
.scaleEffect(scale)
}
}
The 'if' statement was added to minimize the jitter caused by frequent updates. Nothing is special about the 0.94 value, just set by trial and error.
The .animation(spring()) statement was added for a more natural-looking dragging effect.
I found that the easiest way to achieve is to use PDFKit provided by Apple .
1.Start by creating PDFView
import SwiftUI
import PDFKit
struct PhotoDetailView: UIViewRepresentable {
let image: UIImage
func makeUIView(context: Context) -> PDFView {
let view = PDFView()
view.document = PDFDocument()
guard let page = PDFPage(image: image) else { return view }
view.document?.insert(page, at: 0)
view.autoScales = true
view.backgroundColor = .clear
return view
}
func updateUIView(_ uiView: PDFView, context: Context) {
}
}
2.Use in swiftUI view, like this
TabView(selection: $index,
content: {
//this line
PhotoDetailView(image: images[index])
.offset(imageViewerOffset)
})
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With