Animations can transform a mundane interface into a delightful and engaging experience. With SwiftUI, creating visually stunning animations is easier than ever.
In this article, we’ll create an elegant scaling and fading animation using SwiftUI. This animation brings your UI to life with minimal effort and maximum impact.
1. What Makes SwiftUI Animations Unique?
SwiftUI animations are declarative, intuitive, and flexible. With just a few lines of code, you can create:
- Implicit Animations: Automatically animated state changes.
- Explicit Animations: Defined animations using withAnimation blocks.
- Custom Transitions: Animate views entering or exiting the screen.
2. Creating a Stunning Scaling and Fading Animation
Here’s what we’re building:
A circle that scales and fades in/out with a beautiful spring animation when tapped.
Set Up Your SwiftUI View
Let’s start with a clean and organized SwiftUI view.
import SwiftUI
struct SmoothAnimationView: View {
// MARK: - Properties
@State private var isAnimated = false
// MARK: - Body
var body: some View {
VStack {
Spacer()
AnimatedCircle(isAnimated: $isAnimated)
Spacer()
AnimateButton(isAnimated: $isAnimated)
}
.padding()
.background(LinearGradient(colors: [Color.blue.opacity(0.2), Color.purple.opacity(0.1)],
startPoint: .topLeading,
endPoint: .bottomTrailing))
.ignoresSafeArea()
}
}
struct SmoothAnimationView_Previews: PreviewProvider {
static var previews: some View {
SmoothAnimationView()
}
}
SwiftBuild the Animated Circle
Extract the circle into a reusable component for better code organization.
struct AnimatedCircle: View {
// MARK: - Properties
@Binding var isAnimated: Bool
// MARK: - Body
var body: some View {
Circle()
.fill(
LinearGradient(colors: [Color.purple, Color.blue],
startPoint: .top,
endPoint: .bottom)
)
.frame(width: isAnimated ? 200 : 100, height: isAnimated ? 200 : 100)
.opacity(isAnimated ? 1.0 : 0.3)
.scaleEffect(isAnimated ? 1.2 : 0.8)
.shadow(color: .blue.opacity(0.5), radius: isAnimated ? 20 : 5)
.animation(.spring(response: 0.6, dampingFraction: 0.5), value: isAnimated)
}
}
SwiftAdd an Interactive Button
The button toggles the animation state with a satisfying click.
struct AnimateButton: View {
// MARK: - Properties
@Binding var isAnimated: Bool
// MARK: - Body
var body: some View {
Button(action: {
withAnimation {
isAnimated.toggle()
}
}) {
Text(isAnimated ? "Reset Animation" : "Start Animation")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(maxWidth: .infinity)
.background(
LinearGradient(colors: [Color.blue, Color.purple],
startPoint: .leading,
endPoint: .trailing)
)
.cornerRadius(12)
.shadow(color: .blue.opacity(0.3), radius: 10, x: 5, y: 5)
}
.padding(.horizontal)
}
}
Swift3. Why This Design Works
This implementation focuses on:
- Reusability: By splitting the circle and button into separate views, you can reuse and adapt them easily.
- Visual Appeal: Gradients, shadows, and smooth transitions make the animation eye-catching.
- Simplicity: The declarative approach in SwiftUI keeps the code clean and readable.
Running the Code
When you tap the button:
- The circle scales up, fades in, and casts a glowing shadow.
- Tapping the button again reverses the animation.
You’ll notice the spring effect adds a natural bounce to the motion.
4. Enhancements to Try
1. Customize the Timing Curve:
Replace .spring
with .easeInOut
for a more elegant effect:
.animation(.easeInOut(duration: 1.0), value: isAnimated)
Swift2. Add Dynamic Colors:
Use ColorPicker
to let users customize the gradient.
3. Combine Animations:
Layer multiple animations for more complex effects:
.rotationEffect(.degrees(isAnimated ? 360 : 0))
SwiftFinal Result
Here’s what the final animation looks like: