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

Popular posts from this blog

Dependency Injection in iOS with SwiftUI

Using Core ML with SwiftUI: Build an AI-Powered App

CI/CD for iOS Projects with Xcode: A Complete Guide