3D Scroll effect with SwiftUI

Let's preview the 3D scroll effect to be realized today. After learning this tutorial, you can add this 3D effect to any custom SwiftUI view in your App. Let's start this tutorial.

introduction

First, create a new SwiftUI view. For example, in this new view, I will show a rectangular list with various colors and name the new view ColorList.

import SwiftUI

struct ColorList: View {
    var body: some View {
        Text("Hello, World!")
    }
}

struct ColorList_Previews: PreviewProvider {
    static var previews: some View {
        ColorList()
    }
}

Color data

In the structure of the view, add a variable to record the color.

var colors: [Colors]

Implement this list

Inside the body variable, delete the placeholder Text. Add an HStack in the ScrollView nest as follows:

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack(alignment: .center, spacing: 50) {

        }
    }
}

Display rectangle

We use ForEach to create rectangles of different colors within HStack according to the data in colors. In addition, I modified the rectangular frame to make it look more like the traditional UI layout.

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack(alignment: .center, spacing: 20) {
            ForEach(colors, id: \.self) { color in
                Rectangle()
                    .foregroundColor(color)
                    .frame(width: 200, height: 300, alignment: .center)
            }
        }
    }
}

Pass in the following color parameters in the Preview structure:

struct ColorList_Previews: PreviewProvider {
    static var previews: some View {
        ColorList(colors: [.blue, .green, .orange, .red, .gray, .pink, .yellow])
    }
}

You can see the effect in the figure below:

Increase 3D effect

First, nest the Rectangle in the GeometryReader. In this way, when the Rectangle moves on the screen, we can get the reference of its frame.

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack(alignment: .center, spacing: 230) {
            ForEach(colors, id: \.self) { color in
                GeometryReader { geometry in
                    Rectangle()
                        .foregroundColor(color)
                        .frame(width: 200, height: 300, alignment: .center)
                }
            }
        }
    }
}

According to the usage requirements of GeometryReader, we need to modify the spacing attribute of HStack defined above.

Add the following line of code to the Rectangle.

.rotation3DEffect(Angle(degrees: (Double(geometry.frame(in: .global).minX) - 210) / -20), axis: (x: 0, y: 1.0, z: 0))

When the Rectangle moves on the screen, the Angle parameter of this method will change. Focus on the. frame(in:) function. You can obtain the CGRect attribute of Rectangle and the minX variable to calculate the Angle.

The axis parameter is a tuple type, which defines which coordinate axis will change when using the angle parameter you pass in. In this case, it is the Y axis.

The documentation for the rotation3defect () method can be found here on Apple's official website.

Next, run the case. As the rectangles move on the screen, you can see them rotating.

I also modified the cornerRadius property of the rectangle and added the projection effect to make it more beautiful.

Final effect

struct ColorList: View {
    
    var colors:[Color]
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(alignment: .center, spacing: 230) {
                ForEach(colors, id: \.self) { color in
                    GeometryReader { geometry in
                        Rectangle()
                            .foregroundColor(color)
                            .frame(width: 200, height: 300, alignment: .center)
                            .cornerRadius(16)
                            .shadow(color: Color.black.opacity(0.2), radius: 20, x: 0, y: 0)
                            .rotation3DEffect(Angle(degrees: (Double(geometry.frame(in: .global).minX) - 210) / -20), axis: (x: 0, y: 1.0, z: 0))
                    }
                }
            }.padding(.horizontal, 210)
        }
    }
}

end

From: SwiftUI 3D Scroll Effect[2]

reference material

[1]trailingclosure: https://trailingclosure.com/signup/

[2]SwiftUI 3D Scroll Effect: https://levelup.gitconnected.com/swiftui-3d-scroll-effect-fa5310665738

Posted on Thu, 25 Nov 2021 21:52:09 -0500 by clang