Making an attempt to recreate an animation just like how Google shows an increasing impact on hovering an merchandise on internet/desktop however I have never been in a position to nail the animation precisely.
The animation I am making an attempt to attain:
That is what I’ve to date:
There are some points I am operating into:
- animation appears to occur from the middle as an alternative of the left edge with kind of a flash moderately than an develop
- title of the merchandise to the best of the tapped merchandise appears to overlap with the at present tapped merchandise
- the change of picture of the merchandise would not seems precisely the identical, in Google’s animation it seems like a fade in/out kind of impact moderately than a mere substitute that occurs in mine.
My code is as follows:
struct CarouselItem: Identifiable, Equatable {
personal(set) var id: UUID = .init()
var title: String
var 12 months: String
var runtime: String
var certification: String
var posterImage: String
var stillImage: String
}
struct CarousalItemView: View {
@State var merchandise: CarouselItem
@Binding var selectedItem: CarouselItem?
var physique: some View {
if merchandise.id == selectedItem?.id {
selectedItemView()
} else {
unselectedItemView()
}
}
@ViewBuilder func selectedItemView() -> some View {
VStack(alignment: .main) {
ZStack {
Picture(merchandise.stillImage)
.resizable()
.scaledToFill()
.body(width: 250, peak: 200)
.clipShape(RoundedRectangle(cornerRadius: 10))
.overlay(alignment: .main) {
VStack(alignment: .main, spacing: 15) {
Spacer()
Textual content(merchandise.title)
.font(.title2)
HStack {
Textual content("CBFC: " + merchandise.certification)
.padding(.horizontal, 5)
.overlay {
Rectangle()
.stroke(.white, lineWidth: 1)
}
Textual content(merchandise.runtime)
Textual content(merchandise.12 months)
}
.shadow(shade: .grey, radius: 5, y: 5)
Button {
} label: {
Textual content("Trailer")
}
.buttonStyle(.borderedProminent)
.tint(.grey)
.padding(.backside, 15)
}
.padding(.horizontal, 10)
}
}
Textual content(merchandise.title)
.body(peak: 50)
}
}
@ViewBuilder func unselectedItemView() -> some View {
VStack(alignment: .main) {
Picture(merchandise.posterImage)
.resizable()
.scaledToFill()
.body(width: 150, peak: 200)
.clipShape(RoundedRectangle(cornerRadius: 10))
Textual content(merchandise.title)
.body(peak: 50)
}
.foregroundStyle(.white)
}
}
struct ContentView: View {
var objects: [CarouselItem] = [
.init(title: "Oppenheimer", year: "2023", runtime: "3h 1m", certification: "UA", posterImage: "poster1", stillImage: "still1"),
.init(title: "Barbie", year: "2023", runtime: "1h 54m", certification: "PG", posterImage: "poster2", stillImage: "still2"),
.init(title: "The Martian", year: "2015", runtime: "2h 24m", certification: "UA", posterImage: "poster3", stillImage: "still3"),
.init(title: "The Shawshank Redemption", year: "1994", runtime: "2h 22m", certification: "U", posterImage: "poster4", stillImage: "still4"),
.init(title: "The Godfather", year: "1972", runtime: "2h 55m", certification: "UA", posterImage: "poster5", stillImage: "still5"),
.init(title: "The Dark Knight", year: "2008", runtime: "2h 32m", certification: "UA", posterImage: "poster6", stillImage: "still6")
]
@State var selectedItem: CarouselItem?
var physique: some View {
VStack {
HStack {
Textual content("Well-liked movies")
.font(.title2.daring())
Spacer()
}
// MARK: Carousal
ScrollView(.horizontal) {
LazyHStack(spacing: 10) {
ForEach(objects, id: .id) { merchandise in
CarousalItemView(merchandise: merchandise, selectedItem: $selectedItem)
.body(width: selectedItem?.id != merchandise.id ? 150 : 250, peak: 250)
.clipShape(RoundedRectangle(cornerRadius: 10))
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
if selectedItem?.id == merchandise.id {
selectedItem = nil
} else {
selectedItem = merchandise
}
}
}
}
}
}
.body(peak: 250)
.scrollIndicators(.hidden)
.clipped()
Spacer()
}
.padding()
.background {
Colour(.darkGray).ignoresSafeArea()
}
.foregroundStyle(.white)
}
}
Any assistance is appreciated.