Created
July 12, 2022 20:01
-
-
Save DaemonLoki/98b1f462432a6f25e91ea77d19b96d39 to your computer and use it in GitHub Desktop.
Card Flip Animation with a drag.
This file contains 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
import SwiftUI | |
struct ViewContainer: View { | |
var flipped: Bool | |
var isReversed: Bool | |
var body: some View { | |
if flipped { | |
ZStack { | |
RoundedRectangle(cornerRadius: 20, style: .continuous) | |
.fill(.blue) | |
Text("Number 1") | |
.font(.largeTitle) | |
} | |
.rotation3DEffect(.degrees(isReversed ? 180 : 0), axis: (x: 0, y: 1, z: 0)) | |
} else { | |
ZStack { | |
RoundedRectangle(cornerRadius: 20, style: .continuous) | |
.fill(.green) | |
Text("Darn, it works just like that.") | |
} | |
.rotation3DEffect(.degrees(!flipped && !isReversed ? 180 : 0), axis: (x: 0, y: 1, z: 0)) | |
} | |
} | |
} | |
struct ContentView: View { | |
@State private var flipped = false | |
@State private var startFlipped = false | |
@State private var dragAmount: Double = 0 | |
let animationDuration = 0.4 | |
@State private var isReversed = true | |
var body: some View { | |
ViewContainer(flipped: flipped, isReversed: isReversed) | |
.frame(width: 300, height: 300, alignment: .center) | |
.rotation3DEffect(.degrees(dragAmount), axis: (x: 0, y: 1, z: 0)) | |
.gesture( | |
DragGesture() | |
.onChanged({ dragValue in | |
if !flipped && !startFlipped { | |
isReversed = true | |
} | |
dragAmount = dragValue.translation.width | |
if abs(dragAmount.truncatingRemainder(dividingBy: 270)) > 90 { | |
flipped = startFlipped ? false : true | |
} else { | |
flipped = startFlipped ? true : false | |
} | |
}) | |
.onEnded({ dragValue in | |
withAnimation(.easeOut(duration: animationDuration)) { | |
if dragAmount > 270 { | |
dragAmount = 360 | |
startFlipped = false | |
} else if dragAmount < -270 { | |
dragAmount = -360 | |
startFlipped = false | |
} else if dragAmount > 90 { | |
dragAmount = 180 | |
startFlipped = !startFlipped | |
} else if dragAmount < -90 { | |
dragAmount = -180 | |
startFlipped = !startFlipped | |
} else { | |
dragAmount = 0 | |
} | |
} | |
// That's the hack. Putting it to 0 as quiet as leaving the room after the baby sleeps. | |
DispatchQueue.main.asyncAfter(deadline: .now() + animationDuration) { | |
dragAmount = 0 | |
if startFlipped && flipped { | |
isReversed = false | |
} else if !flipped && !isReversed && !startFlipped { | |
isReversed = true | |
} | |
} | |
}) | |
) | |
} | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
ContentView() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment