I have not been able to find an equivalent to the pan gesture in SwiftUI. I do see and use magnify, tap, drag and rotate - but I do not see any built in pan. In the following code snippet I add an image and allow the user to zoom - but I want the user to also move the zoomed image to focus on the area of interest. Dragging, of course does not do the job - it just moves the frame.
I tried layering a frame on top and moving the bottom image but could not make that work either.
struct ContentView: View {
@State var scale: CGFloat = 1.0
@State var isScaled: Bool = false
@State private var dragOffset = CGSize.zero
var body: some View {
GeometryReader { geo in
VStack {
ZStack{
RoundedRectangle(cornerRadius: 40)
.foregroundColor(Color.white)
.frame(width: geo.size.width - 45, height: geo.size.width - 45)
.shadow(radius: 10)
Image("HuckALaHuckMedium")
.resizable()
.scaleEffect(self.scale)
.frame(width: geo.size.width - 60, height: geo.size.width - 60)
.cornerRadius(40)
.aspectRatio(contentMode: .fill)
.shadow(radius: 10, x: 20, y: 20)
//need pan not drag
.gesture(
DragGesture()
.onChanged { self.dragOffset = $0.translation }
.onEnded { _ in self.dragOffset = .zero }
)
//this works but you can't "zoom twice"
.gesture(MagnificationGesture()
.onChanged { value in
self.scale = self.isScaled ? 1.0 : value.magnitude
}
.onEnded({ value in
//self.scale = 1.0
self.isScaled.toggle()
})
)
.animation(.easeInOut)
.offset(self.dragOffset)
}//zstack
Spacer()
}
}
}
}
An original image example:
And that image after zoom - but with drag not pan:
Any guidance would be appreciated. Xcode 11.3 (11C29)
As mentioned earlier, SwiftUI has a built-in modifier for applying overlay named .overlay that can be attached to the existing image view. The requirement inside an overlay modifier is to place another object that will serve as the coating of the image.
Add a header title above the image and position it towards the top of the screen: Position the image within a custom frame: Note that I’m using the SwiftUI canvas live preview of my code and it highlighted the border of my custom frame because I kept the blinking cursor on the Image code.
In order to add it to your Xcode project, download it to your computer, click on Assets.xcassets in Xcode project and drag and drop the image onto the list of assets. Follow this introductory tutorial on how to add image to Xcode project in SwiftUI.
A basic familiarity with Swift. The most popular magnification gesture can be found in photos, where you can magnify a photo by scaling it larger or smaller. Now, you will attempt to magnify a Tesla image. You will need a GestureState to store the value. The n, you will need to create an image that will also take the scale value.
To make it simpler and more readable, I created an extension/modifier for that
struct DraggableView: ViewModifier {
@State var offset = CGPoint(x: 0, y: 0)
func body(content: Content) -> some View {
content
.gesture(DragGesture(minimumDistance: 0)
.onChanged { value in
self.offset.x += value.location.x - value.startLocation.x
self.offset.y += value.location.y - value.startLocation.y
})
.offset(x: offset.x, y: offset.y)
}
}
extension View {
func draggable() -> some View {
return modifier(DraggableView())
}
}
Now all you have to do is call the modifier:
Image(systemName: "plus")
.draggable()
For others. This is really simple. Ensure that the magnification is accomplished before the drag is allowed - it will work like a pan. First define the drag gesture:
let dragGesture = DragGesture()
.onChanged { (value) in
self.translation = value.translation
}
.onEnded { (value) in
self.viewState.width += value.translation.width
self.viewState.height += value.translation.height
self.translation = .zero
}
Then create an @State value that you toggle to true after the magnification gesture has been activated. When you attach the gesture to the image, do so conditionally:
.gesture(self.canBeDragged ? dragGesture : nil)
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