Creating a Scrolling Parallax Effect with SwiftUI
SwiftUI, renowned for its elegance and simplicity, offers an exciting canvas for crafting visually compelling user interfaces. In this tutorial, we’ll embark on a journey to master the art of creating a mesmerizing parallax effect using SwiftUI. Our canvas will be adorned with city cards, represented by the CityCard
model.
Introducing the CityCard
Model
struct CityCard: Identifiable, Hashable {
var id: UUID = .init()
var title: String
var subTitle: String
var image: String
}
// Sample data for trip cards
var tripCards: [CityCard] = [
.init(title: "Mumbai", subTitle: "India", image: "Pic 3"),
.init(title: "New York", subTitle: "USA", image: "Pic 2"),
.init(title: "London", subTitle: "England", image: "Pic 1"),
.init(title: "Alaska", subTitle: "USA", image: "Pic 5"),
.init(title: "Paris", subTitle: "France", image: "Pic 4")
]
Our journey begins with defining the CityCard
model, encapsulating the essence of each city card – title, subtitle, and a captivating image.
Crafting the Parallax Symphony in ContentView
Part 1: Grasping the dimensions with GeometryReader
struct ContentView: View {
var body: some View {
VStack {
GeometryReader(content: { geometry in
let size = geometry.size
Part 2: Horizontal ScrollView, the stage for the parallax effect
GeometryReader(content: { geometry in
let size = geometry.size
ScrollView(.horizontal) {
HStack(spacing: 5) {
Part 3: Embarking on a journey through tripCards
ScrollView(.horizontal) {
HStack(spacing: 5) {
ForEach(tripCards) { card in
Part 4: Grasping individual card dimensions
HStack(spacing: 5) {
ForEach(tripCards) { card in
GeometryReader(content: { geo in
let cardSize = geo.size
let minX = min(geo.frame(in: .scrollView).minX * 1.4, geo.size.width * 1.4)
Part 5: Elevating the Parallax Image
GeometryReader(content: { geo in
let cardSize = geo.size
let minX = min(geo.frame(in: .scrollView).minX * 1.4, geo.size.width * 1.4)
Image(card.image)
.resizable()
.aspectRatio(contentMode: .fill)
.scaleEffect(1.2)
.offset(x: -minX)
.frame(width: cardSize.width, height: cardSize.height)
Part 6: Enchanting overlay with city name
Image(card.image)
.resizable()
.aspectRatio(contentMode: .fill)
.scaleEffect(1.2)
.offset(x: -minX)
.frame(width: cardSize.width, height: cardSize.height)
.overlay {
addCityName(card: card)
}
.clipShape(.rect(cornerRadius: 15))
.shadow(color: .black.opacity(0.25), radius: 8, x: 5, y: 10)
})
Part 7: Adding finesse with size and scale transition
.overlay {
addCityName(card: card)
}
.clipShape(.rect(cornerRadius: 15))
.shadow(color: .black.opacity(0.25), radius: 8, x: 5, y: 10)
})
.frame(width: size.width - 60, height: size.height - 50)
.scrollTransition(.interactive, axis: .horizontal) { view, phase in
view.scaleEffect(phase.isIdentity ? 1 : 0.95)
}
}
}
.padding(.horizontal, 30)
.scrollTargetLayout()
.frame(height: size.height, alignment: .top)
}
.scrollTargetBehavior(.viewAligned)
.scrollIndicators(.hidden)
})
.frame(height: 550)
.padding(.horizontal, -15)
.padding(.top, 10)
}
.padding(15)
}
}
In this symphony of SwiftUI, we gracefully introduce the ContentView
structure, harmonizing the elements to create an immersive parallax effect. Each part plays a crucial role, contributing to the overall masterpiece.
Enchanting the Overlay: addCityName
Function
@ViewBuilder
func addCityName(card: CityCard) -> some View {
let gardientColors : [Color] = [.clear,.clear,.clear,.clear,.clear,.black.opacity(0.1),.black.opacity (0.5),.black]
ZStack(alignment:
.bottomLeading, content: {
LinearGradient (colors: gardientColors,
startPoint: .top, endPoint: .bottom)
VStack(alignment: .leading, spacing: 4,content:{
Text (card.title)
.font(.title2)
.fontWeight(.black)
.foregroundStyle(.white)
Text (card.subTitle)
.font(.callout)
.foregroundStyle(.white.opacity(0.8))
})
.padding(20)
})
}
The addCityName
function enchants our city cards with an elegant overlay, showcasing the city's title and subtitle in a beautifully stylized format.
Open Source Goodness: GitHub Repository
Explore and experiment with the code by accessing the GitHub repository:
SwiftUI Parallax Demo — https://github.com/PrathameshBhuravane/Parallax.git
Clone the repository to dive into the details and contribute to the magic.
Conclusion
With SwiftUI’s elegance and our orchestration skills, we’ve created a mesmerising parallax effect that breathes life into city cards. The CityCard
model lays the foundation, and the ContentView
structure orchestrates a symphony of visuals. As you continue your SwiftUI journey, let this tutorial serve as a guide to mastering the art of parallax effects in your applications. Happy coding!