Skip to content

Instantly share code, notes, and snippets.

@swiftui-lab
Created September 25, 2019 12:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save swiftui-lab/a2fec9c4eff874e8ae21076763744335 to your computer and use it in GitHub Desktop.
Save swiftui-lab/a2fec9c4eff874e8ae21076763744335 to your computer and use it in GitHub Desktop.
// Advanced SwiftUI Transitions
// https://swiftui-lab.com
// https://swiftui-lab.com/advanced-transitions
import SwiftUI
struct GeometryEffectTransitionsDemo: View {
@State private var show = false
var body: some View {
return ZStack {
Button("Open Booking") {
withAnimation(.easeInOut(duration: 0.8)) {
self.show = true
}
}
if show {
RoundedRectangle(cornerRadius: 15)
.fill(Color.pink).overlay(MyForm(show: $show))
.frame(width: 400, height: 500)
.shadow(color: .black, radius: 3)
.transition(.fly)
.zIndex(1)
}
}
}
}
struct MyForm: View {
@Binding var show: Bool
@State private var departure = Date()
@State private var checkin = Date()
@State private var pets = true
@State private var nonsmoking = true
@State private var airport: Double = 7.3
var body: some View {
VStack {
Text("Booking").font(.title).foregroundColor(.white)
Form {
DatePicker(selection: $departure, label: {
HStack {
Image(systemName: "airplane")
Text("Departure")
}
})
DatePicker(selection: $checkin, label: {
HStack {
Image(systemName: "house.fill")
Text("Check-In")
}
})
Toggle(isOn: $pets, label: { HStack { Image(systemName: "hare.fill"); Text("Have Pets") } })
Toggle(isOn: $nonsmoking, label: { HStack { Image(systemName: "nosign"); Text("Non-Smoking") } })
Text("Max Distance to Airport \(String(format: "%.2f", self.airport as Double)) km")
Slider(value: $airport, in: 0...10) { EmptyView() }
Button(action: {
withAnimation(.easeInOut(duration: 1.0)) {
self.show = false
}
}) {
HStack { Spacer(); Text("Save"); Spacer() }
}
}
}.padding(20)
}
}
extension AnyTransition {
static var fly: AnyTransition { get {
AnyTransition.modifier(active: FlyTransition(pct: 0), identity: FlyTransition(pct: 1))
}
}
}
struct FlyTransition: GeometryEffect {
var pct: Double
var animatableData: Double {
get { pct }
set { pct = newValue }
}
func effectValue(size: CGSize) -> ProjectionTransform {
let rotationPercent = pct
let a = CGFloat(Angle(degrees: 90 * (1-rotationPercent)).radians)
var transform3d = CATransform3DIdentity;
transform3d.m34 = -1/max(size.width, size.height)
transform3d = CATransform3DRotate(transform3d, a, 1, 0, 0)
transform3d = CATransform3DTranslate(transform3d, -size.width/2.0, -size.height/2.0, 0)
let affineTransform1 = ProjectionTransform(CGAffineTransform(translationX: size.width/2.0, y: size.height / 2.0))
let affineTransform2 = ProjectionTransform(CGAffineTransform(scaleX: CGFloat(pct * 2), y: CGFloat(pct * 2)))
if pct <= 0.5 {
return ProjectionTransform(transform3d).concatenating(affineTransform2).concatenating(affineTransform1)
} else {
return ProjectionTransform(transform3d).concatenating(affineTransform1)
}
}
}
@mamboer
Copy link

mamboer commented Nov 11, 2019

hi, i copied and ran this demo at xcode 11.2,
and found that no transition effects on opening the form,
i recorded a short screen-shot here:

https://www.weiyun.com/video_preview?videoID=7be112f8-9711-436e-88b9-55bf7f3df317&fileName=IMG_6897.MOV&dirKey=d5685607e369b1badf4565554c2e2b6a&pdirKey=&shareKey=5wp7ber

Thanks for the amazing article and the demo. 👍

@swiftui-lab
Copy link
Author

swiftui-lab commented Nov 11, 2019 via email

@swiftui-lab
Copy link
Author

swiftui-lab commented Nov 15, 2019 via email

@ranveerm
Copy link

I removed the line with .zIndex(1) noticed that the fly transition would not animate in the "dismissal phase" (the view would still animate when it appeared). I couldn't ascertain why this is required from the documentation (and I don't believe you mentioned this in your post). Could you please explain the need for this? Also, if you noticed the view from failing to animate appropriately during the development process, how did you go about debugging in order to reach the above conclusion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment