HomeiOS Developmentios - Animate SwiftUI Scrollview merchandise from left edge

ios – Animate SwiftUI Scrollview merchandise from left edge


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:

enter image description here

That is what I’ve to date:

enter image description here

There are some points I am operating into:

  1. animation appears to occur from the middle as an alternative of the left edge with kind of a flash moderately than an develop
  2. title of the merchandise to the best of the tapped merchandise appears to overlap with the at present tapped merchandise
  3. 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.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments