SwiftUI Animation
Basic Animations in SwiftUI can easily be created using state variables and adjusting them within withAnimation blocks. In this example a view's offset is controlled using a drag gesture. When dragging exceeds a threshold, a new animation is started.
import SwiftUI struct SampleAnimationView: View { @State var taskQuestion: String = "1 + 1" @State var taskIndex: Int = 1 @State var taskDragActive: Bool = false @State var taskDragEndDone: Bool = false let actionThreshold: CGFloat = -100.0 @State var actionValue: CGFloat = 0.0 @State var opacityValue: CGFloat = 1.0 @State var offsetValue: CGFloat = 0.0 var body: some View { VStack(spacing: 0) { VStack { HStack { Text(taskQuestion) .frame(maxWidth: .infinity) } .font(.system(size: 40)) .opacity(opacityValue) .offset(x: offsetValue, y: 0) } .padding(5) .frame(maxWidth: .infinity) .background(content: { RoundedRectangle(cornerRadius: 16) .fill(Color.white) .opacity(0.30) }) .gesture( DragGesture( minimumDistance: 5.0, coordinateSpace: .global) .onChanged({ value in if !taskDragActive { taskDragActive = true taskDragEndDone = false } actionValue = value.translation.width opacityValue = max(1.0 - abs(actionValue) * 0.01, 0.0) offsetValue = actionValue if actionValue < actionThreshold { if !taskDragEndDone { taskDragEndDone = true } } }) .onEnded({ value in if actionValue >= actionThreshold { taskDragActive = false withAnimation { actionValue = 0 opacityValue = 1.0 offsetValue = 0 } } else if taskDragEndDone { animateNextTask() animateGestureForTask() } }) ) .padding(.vertical, 8) .foregroundStyle(.primary) VStack { Text("Swipe for a new task.") .foregroundStyle(.secondary) .font(.system(size: 14)) .multilineTextAlignment(.center) } } .padding(30) .background { Image("background") .resizable() .scaledToFill() .padding(-80) .blur(radius: 150.0) .brightness(0.3) } } private func animateGestureForTask() { opacityValue = 0.0 offsetValue = 150.0 withAnimation(.spring(duration: 0.8, bounce: 0.1)) { offsetValue = 0.0 } withAnimation(.easeOut(duration: 1.8)) { opacityValue = 1.0 } } private func animateNextTask() { taskIndex += 1 taskQuestion = "\(taskIndex) + \(taskIndex)" } } #Preview { SampleAnimationView() }
