Last active
January 8, 2021 14:25
-
-
Save zahmedpk/803b6a2ba8da0ead4cc54d82e2a9fec7 to your computer and use it in GitHub Desktop.
Use multiple gestures to interact with an object.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SwiftUI Gestures Tiny Example | |
// Xcode 12.3 | |
// This gist shows how to use multiple gestures on same object. | |
// We draw a rectangle on screen that can be | |
// 1. pinch zoomed | |
// 2. rotated | |
// 3. tapped (single tap) to change opacity | |
// 4. tapped (double tap) to change color | |
// 5. long press to scale up (+0.2) | |
import SwiftUI | |
struct ContentView: View { | |
@State var translationXDuringDrag: CGFloat = 0.0 | |
@State var translationYDuringDrag: CGFloat = 0.0 | |
@State var translationXCumulative: CGFloat = 0.0 | |
@State var translationYCumulative: CGFloat = 0.0 | |
@State var transientZoomScale: CGFloat = 1.0 | |
@State var steadyStateZoomScale: CGFloat = 1.0 | |
@State var alpha: CGFloat = 0.3 | |
@State var color: UIColor? | |
@State var transientRotation: Angle = Angle.init(degrees: 0) | |
@State var steadyStateRotation: Angle = Angle.init(degrees: 0) | |
let colors = [UIColor.blue, UIColor.systemPink, UIColor.yellow, UIColor.green] | |
var zoomScale: CGFloat { | |
transientZoomScale * steadyStateZoomScale | |
} | |
var rotation: Angle { | |
steadyStateRotation + transientRotation | |
} | |
var body: some View { | |
VStack { | |
Color(color == nil ? UIColor.blue.withAlphaComponent(alpha) : color!.withAlphaComponent(alpha)) | |
.frame(width: 200, height: 200, alignment: .center) | |
.cornerRadius(10) | |
.scaleEffect(zoomScale) | |
.rotationEffect(rotation) | |
.transformEffect(.init(translationX: translationXCumulative+translationXDuringDrag, y: translationYCumulative+translationYDuringDrag)) | |
.gesture(dragGesture) | |
.gesture(rotationAndMagnification) | |
.onTapGesture(count: 2) { | |
color = colors.filter {$0 != color}.randomElement() | |
} | |
.onTapGesture { | |
alpha += 0.2 | |
if alpha > 0.8 { | |
alpha = 0.1 | |
} | |
} | |
.onLongPressGesture { | |
withAnimation { | |
steadyStateZoomScale += 0.2 | |
} | |
} | |
} | |
.background(Text( | |
""" | |
box can be | |
1. dragged | |
2. pinch zoomed/rotated. | |
3. Single tap to change alpha | |
4. Double tap changes color | |
5. Long press zooms up incrementally | |
""" | |
)) | |
} | |
var dragGesture: some Gesture { | |
DragGesture() | |
.onChanged { (value) in | |
translationXDuringDrag = value.translation.width | |
translationYDuringDrag = value.translation.height | |
} | |
.onEnded { value in | |
translationXCumulative += value.translation.width | |
translationYCumulative += value.translation.height | |
translationXDuringDrag = 0 | |
translationYDuringDrag = 0 | |
} | |
} | |
var magnificationGesture: some Gesture { | |
MagnificationGesture() | |
.onChanged({ (value) in | |
transientZoomScale = value | |
}) | |
.onEnded { (finalValue) in | |
transientZoomScale = 1 | |
steadyStateZoomScale *= finalValue | |
} | |
} | |
var rotationGesture: some Gesture { | |
RotationGesture() | |
.onChanged { (angle) in | |
transientRotation = angle | |
} | |
.onEnded { (finalAngle) in | |
steadyStateRotation += finalAngle | |
transientRotation = Angle() | |
} | |
} | |
var rotationAndMagnification: some Gesture { | |
rotationGesture.simultaneously(with: magnificationGesture) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment