32: Animations, part 1

그루두·2024년 5월 18일
0

100 days of SwiftUI

목록 보기
41/108

100 days of swiftui: 32
https://www.hackingwithswift.com/100/swiftui/32

implicit animation

Double 값을 이용해서 View의 크기와 형태를 변경하고 이를 애니메이션으로 연결할 수 있다.

  • scaleEffect
.scaleEffect(animationAmount)
  • animation
.animation(.snappy, value: animationAmount)

다양한 버전으로 애니메이션 형태를 설정할 수 있다.

  • blur
.blur(radius: (animationAmount - 1) * 2)

전체 코드

struct ContentView: View {
    @State private var animationAmount = 1.0
    var body: some View {
        Button("Tap here") {
            animationAmount += 0.5
        }
        .padding(40)
        .background(.blue)
        .foregroundColor(.white)
        .clipShape(Circle())
        .blur(radius: (animationAmount - 1) * 2)
        .scaleEffect(animationAmount)
        .animation(.snappy, value: animationAmount)
    }
}

코드 파일
https://github.com/treesofgroo/Ios-Animations/commit/8eda067698b102a7b15c6a2383e90a6ec2ae882b

delay, repeat

delay를 이용해서 애니메이션의 시작 순간을 늦출 수 있다. 그리고 repeatCount를 통해 애니메이션의 반복 횟수를 설정할 수 있다. 설정한 대로 애니메이션을 한 번 실행시키고, 다시 돌아오는 형태로 애니메이션을 한 번 실행시키면서 반복을 실행하기 때문에 홀수번 반복하면 최종 형태까지 애니메이션이 실행되고, 짝수번 반복하면 다시 원래대로 돌아오는 애니메이션을 실행한 후 최종 형태가 된다.

예: delay: 1, repeatCount: 2 or 3

그리고 변수값을 설정하는 순간과 View가 나타날때의 시간 차이를 이용해서 애니메이션을 설정할 수도 있다. 아래 예시는 animationAmount를 1.0으로 설정하고 onAppear에서는 값을 2로 설정하고 마지막으로 repeatForever를 통해 애니메이션을 계속 반복시켰다.

        Button("Tap here") {}
            .padding(40)
            .background(.blue)
            .foregroundColor(.white)
            .clipShape(.circle)
            .overlay(
                Circle()
                    .stroke(.blue)
                    .scaleEffect(animationAmount)
                    .opacity(2 - animationAmount)
                    .animation(
                        .easeInOut(duration: 1.5)
                        .repeatForever(autoreverses: true),
                        value: animationAmount
                    )
            )
            .onAppear {
                animationAmount = 2
            }

코드 파일
https://github.com/treesofgroo/Ios-Animations/commit/a7312068d4969940faaadcf920865fdf81128218

animation binding

binding인 값을 animation으로 적용시켜 사용할 수 있다. 아래 예시는 위와 달리 binding 값 animationAmount에 animation을 적용시켰다.

    @State private var animationAmount = 1.0
    var body: some View {
        VStack {
            Button("Tap here") {}
                .padding(40)
                .background(.blue)
                .foregroundColor(.white)
                .clipShape(.circle)
                .scaleEffect(animationAmount)
            Spacer()
            Stepper("Amount of animation", value: $animationAmount.animation(
                .default
            ), in: 1...5)
        }
        .padding()
    }

코드 파일
https://github.com/treesofgroo/Ios-Animations/commit/a7cf6ea41bdba398e0626db2aa36f69012b0c243

explicit animation

위의 예시는 View나 binding에 .animation을 이용했다. 이는 implicit 방식이고, 반대로 explicit 방식도 있다.

아래 예시는 3d 공간에서 회전하고, withAnimation {}을 활용해 animationAmount값이 바뀌는 걸 animation을 적용한다.

            Button("Tap here") {
                withAnimation(.spring(duration: 1, bounce: 0.6)) {
                    animationAmount += 360
                }
            }
                .padding(50)
                .background(.blue)
                .foregroundColor(.white)
                .clipShape(.circle)
                .rotation3DEffect(
                    .degrees(animationAmount), axis: (x: 1.0, y: 1.0, z: 1.0))
        }

참고로 implicit 방법을 활용한 코드는 아래이다. 동작은 똑같다.

            Button("Tap here") {
                animationAmount += 360
            }
                .padding(50)
                .background(.blue)
                .foregroundColor(.white)
                .clipShape(.circle)
                .rotation3DEffect(
                    .degrees(animationAmount), axis: (x: 1.0, y: 1.0, z: 1.0))
                .animation(.spring(duration: 1, bounce: 0.6), value: animationAmount)

코드 파일
https://github.com/treesofgroo/Ios-Animations/commit/a5041b1c1545b5a0c32c732fc69fd74c90c0a160

profile
계속 해보자

0개의 댓글

관련 채용 정보