티스토리 뷰

반응형

SwiftUI Tutorials > Animating Views and Transitions 에 나오는 내용을 기반으로 하고 있습니다. 

 

목표

SwiftUI가 제공하는 effect 들을 써보고 (이 글에서는 rotationEffect, scaleEffect 사용)

여러 effect를 조합하여 애니메이션 시키는 법을 알아봅니다. 

 

 

 

 

[1] rotationEffect

struct DetailButtonImage: View {
    var body: some View {
        Image(systemName: "chevron.right")
            .frame(width: 50, height: 50)
            .background(
                Circle().foregroundColor(.white)  // Shape의 fill을 써도 됨.
            )
            .shadow(radius: 5)
    }
}

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .onTapGesture {
                showDetail.toggle()
            }
    }
}

 

 

 

 

너무 로봇같으니까;; 애니메이션을 줘보겠습니다. 

두가지 방법이 있습니다. 

 

 

방법 1. 

 

animation(_:value:) 으로 애니매이션을 줍니다. 

 

 

Animation에서 원하는 애니매이션을 골라주고 애니메이션을 트리거할 value 를 넣어줍니다.  (value가 바뀔때마다 animation이 적용됨) 

 

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .animation(.easeOut, value: showDetail)
            .onTapGesture {
                showDetail.toggle()
            }
    }
}

 

 

방법 2. 

 

withAnimation(_:_:) 을 사용해줍니다.

'Returns the result of recomputing the view’s body with the provided animation' 해주는 친구이고 modifier는 아닙니다. 

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .onTapGesture {
                withAnimation(.easeOut) {
                    showDetail.toggle()
                }
            }
    }
}

 

 

 

 

두 방법의 차이

 

SwiftUI > Animations 에서는 아래와 같이 가이드하고 있습니다. 

 

-  Animate all of the visual changes for a state change by changing the state inside a call to the withAnimation(_:_:) global function.

 

- Add animation to a particular view when a specific value changes by applying the animation(_:value:) view modifier to the view.

 

 

[2] scaleEffect

scaleEffect도 추가해보겠습니다.

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .scaleEffect(showDetail ? 1.5 : 1)
            .animation(.easeOut, value: showDetail)
            .onTapGesture {
                showDetail.toggle()
            }
    }
}

 

또는

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .scaleEffect(showDetail ? 1.5 : 1)
            .onTapGesture {
                withAnimation(.easeOut) {
                    showDetail.toggle()
                }
            }
    }

 

 

 

 

[3]  effect 별 애니메이션

위의 예제를 보면, 하나의 animation이 여러 effect 들에 다 적용되는 것을 볼 수 있습니다. 

effect 별로 animation을 다르게 적용해줄 수도 있습니다.  

 

 

# rotationEffect 는 애니메이션 안시키고 싶고, scaleEffect 만 애니메이션 시키고 싶을 때

 

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .animation(nil, value: showDetail)
            .scaleEffect(showDetail ? 1.5 : 1)
            .animation(.easeOut, value: showDetail)
            .onTapGesture {
                showDetail.toggle()
            }
    }
}

 

애니메이션 안시키고 싶을 때, 

animation에 nil 또는 .none 을 넣어줍니다. 

(SwiftUI Tutorials > Animating Views and Transitions 에서 withoutAnimation(_:) 모디파이어도 있다고 하는데 사라진 것 같아요)

 

이렇게 하면 제일 깔끔한데 value를 안넣어줄 수 있는 인터페이스는 deprecated 되었다고 나오네요;;

(그래서 extension 만들어서 쓰는 분도 있고,,,)

 

 

 

 

 

 

 

# 두개의 effect를 다른 애니메이션으로 적용하고 싶을 때 

struct ContentView: View {
    
    @State private var showDetail = false

    var body: some View {
        DetailButtonImage()
            .rotationEffect(.degrees(showDetail ? 90 : 0))
            .animation(.easeOut(duration: 5), value: showDetail)
            .scaleEffect(showDetail ? 1.5 : 1)
            .animation(.spring(), value: showDetail)
            .onTapGesture {
                showDetail.toggle()
            }
    }
}

 

 

 

 

[4] 궁금

SwiftUI > Shape 에 rotation, scale 등이 있는데..

이것도 rotationEffect, scaleEffect 랑 똑같은 효과를 내는 것인가? 

 

 

 

 

# rotation, scale 일 때 

struct ContentView: View {
    
    @State private var animate = false

    var body: some View {
        Rectangle()
            .rotation(.degrees(animate ? 90 : 0))
            .scale(animate ? 1.5 : 1)
            .animation(.easeOut, value: animate)
            .frame(width: 50, height: 50)
            .onTapGesture {
                animate.toggle()
            }
    }
}

 

 

 

 

# roationEffect, scaleEffect 일 때

struct ContentView: View {
    
    @State private var animate = false

    var body: some View {
        Rectangle()
            .rotationEffect(.degrees(animate ? 90 : 0))
            .scaleEffect(animate ? 1.5 : 1)
            .animation(.easeOut, value: animate)
            .frame(width: 50, height: 50)
            .onTapGesture {
                animate.toggle()
            }
    }
}

 

내 눈에는 똑같아보인다!

 

 

반응형
댓글