How to Create a 3D Parallax Effect in SwiftUI
Adding subtle motion and depth to your iOS UI can greatly enhance the user experience. One of the most visually captivating techniques is the 3D parallax effect — where the foreground and background elements move at different speeds based on user interaction or device movement.
In this post, we’ll walk through creating a 3D parallax effect in SwiftUI using GeometryReader
and @GestureState
.
✨ What is a Parallax Effect?
Parallax is a visual effect where objects closer to the viewer move faster than objects farther away. It gives a sense of depth and motion, often seen in games, interactive UIs, and lock screens.
In SwiftUI, we can simulate this using gesture data or device motion to shift elements slightly based on user input.
🎯 What We’ll Build
A card-style view that responds to drag gestures with a dynamic 3D tilt and layered movement — mimicking real-world parallax.
🚧 Basic Setup
Let’s start with a simple layered card view:
struct ParallaxCardView: View {
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
VStack {
Text("3D Parallax")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.padding()
ParallaxCard()
.frame(width: 300, height: 200)
}
}
}
}
🔁 Adding the Parallax Layers
We’ll create multiple layers with varying offsets:
struct ParallaxCard: View {
@GestureState private var dragOffset = CGSize.zero
var body: some View {
let dragGesture = DragGesture(minimumDistance: 0)
.updating($dragOffset) { value, state, _ in
state = value.translation
}
return ZStack {
// Background Layer
Image("background")
.resizable()
.scaledToFill()
.offset(x: dragOffset.width * 0.1, y: dragOffset.height * 0.1)
// Midground Layer
Image("midground")
.resizable()
.scaledToFill()
.offset(x: dragOffset.width * 0.3, y: dragOffset.height * 0.3)
// Foreground Content
VStack {
Text("Explore")
.font(.title)
.foregroundColor(.white)
.bold()
}
.offset(x: dragOffset.width * 0.5, y: dragOffset.height * 0.5)
}
.frame(width: 300, height: 200)
.clipShape(RoundedRectangle(cornerRadius: 20))
.shadow(radius: 10)
.rotation3DEffect(
.degrees(Double(dragOffset.width / 10)),
axis: (x: 0, y: -1, z: 0)
)
.rotation3DEffect(
.degrees(Double(dragOffset.height / 10)),
axis: (x: -1, y: 0, z: 0)
)
.gesture(dragGesture)
}
}
🧠 How It Works
@GestureState
tracks the user's drag movement in real-time.- Each visual layer is offset by a different multiplier to simulate depth.
- The
rotation3DEffect
tilts the card based on drag position, enhancing the 3D feel.
🌟 Optional Enhancements
- Use
MotionManager
to respond to device tilt (using CoreMotion). - Add a spring animation to reset position on gesture end.
- Blend with shadows or lighting effects for realism.
📲 Final Result
You now have a responsive, swipeable parallax UI in SwiftUI — a great way to create engaging onboarding cards, feature highlights, or interactive backgrounds.
🧩 Conclusion
The 3D parallax effect is surprisingly easy to achieve in SwiftUI and can bring a polished, dynamic feel to your apps. Try experimenting with different layers, images, or even interactive elements.
Comments
Post a Comment