SWIFTUI/Others

SwiftUI : 애니메이션과 비슷한 Transitions

서근 2021. 5. 10. 20:13
반응형

Transition 에 대해 알아보도록 합시다.

Transitons

TransitionsAnimation과 매우 유사한 기능입니다. 하지만 이것을 사용하기 위해서는 반드시 조건부가 필요합니다. 확실히 animation을 사용하는 것보다는 복잡하죠. 바로 코드로 한번 알아볼게요.

 

기본적으로 버튼이 false이면 도형이 숨겨지고 true이면 나타나게 opactiy를 사용하여 구현할 수 있습니다.

import SwiftUI

struct ContentView: View {
    @State var transitionView: Bool = false
    var body: some View {
        ZStack(alignment: .bottom) {
            
            VStack{
                Button("버튼") {
                    transitionView.toggle()
                }
                Spacer()
            }
            RoundedRectangle(cornerRadius: 20)
                .frame(height: UIScreen.main.bounds.height * 0.5)
                .opacity(transitionView ? 1.0 : 0.0)
                .animation(.easeIn)
        }
    }
     .ignoresSafeArea(edges: .bottom)
}

또한 opacity를 사용할 수 도 있겠죠.

ZStack(alignment: .bottom) {
    
    VStack{
        Button("버튼") {
            transitionView.toggle()
        }
        Spacer()
    }
    
    if transitionView {
        RoundedRectangle(cornerRadius: 20)
            .frame(height: UIScreen.main.bounds.height * 0.5)
            .animation(.easeIn)
    }
}
 .ignoresSafeArea(edges: .bottom)

이제 transition을 사용해볼까요?

먼저 제일 효과가 두드러지게 나타나는 slide부터 적용해보겠습니다.

transition(.slide)

            if transitionView {
            RoundedRectangle(cornerRadius: 20)
                .frame(height: UIScreen.main.bounds.height * 0.5)
                .transition(.slide)
                .animation(.easeIn)
                
            }

오른쪽에서 왼쪽으로 물 흐르듯 자연스럽게 나타납니다. 정말 신기하네요 ㅎㅎ 

.transition(.move(edge: .bottom))

            if transitionView {
            RoundedRectangle(cornerRadius: 20)
                .frame(height: UIScreen.main.bounds.height * 0.5)
                .transition(.move(edge: .bottom))
                .animation(.easeIn)
                
            }

지금 도형은 아래쪽에 붙어서 생성되어있죠? 그렇기 때문에 move부분 위치를 bottom으로 정해주게 된다면 팝업 효과를 줄 수 있습니다.

top으로 설정하면 어떨까요? 실제로 보기 좋진 않네요.

AnyTransition

그런데 opactiy를 적용하려고 해 보면 무슨 일인지 제대로 적용이 되질 않습니다. 🤔 이것을 사용하려면 조금 복잡해집니다. 하지만 매우 재미있는 기능이기 때문에 알아두시면 좋습니다.

Opacity

.transition(AnyTransition.opacity.animation(.easeInOut))으로 코드를 작성하고 밑에 부여했던 animation부분은 삭제합니다.

struct ContentView: View {
    @State var transitionView: Bool = false
    var body: some View {
        ZStack(alignment: .bottom) {
            
            VStack{
                Button("버튼") {
                    transitionView.toggle()
                }
                Spacer()
            }
        
            if transitionView {
            RoundedRectangle(cornerRadius: 20)
                .frame(height: UIScreen.main.bounds.height * 0.5)
                .transition(AnyTransition.opacity.animation(.easeInOut))
//                .animation(.easeIn)
            }
        }
        .ignoresSafeArea(edges: .bottom)
    }
}

제대로 효과가 적용되네요. 더 재미있는 기능을 사용해볼까요?

Scale

if transitionView {
    RoundedRectangle(cornerRadius: 20)
        .frame(height: UIScreen.main.bounds.height * 0.5)
        .transition(AnyTransition.scale.animation(.easeInOut))
}

asymmetric

처음 이것을 보고 가장 흥미로웠던 수정자입니다. 바로 asymmetric라는 수정자인데 insertion(시작하는 지점), removal(사라지는 지점)을 정해줄 수 있습니다. 바로 적용해볼게요.

if transitionView {
    RoundedRectangle(cornerRadius: 20)
        .frame(height: UIScreen.main.bounds.height * 0.5)
        //밑에서 등장해서 왼쪽으로 사라짐
        .transition(.asymmetric(insertion: AnyTransition.move(edge: .bottom),
                                removal: AnyTransition.move(edge: .leading)))
        .animation(.easeIn)
}

위에서 했던 것을 아래처럼 사용할 수 있습니다.

if transitionView {
    RoundedRectangle(cornerRadius: 20)
        .frame(height: UIScreen.main.bounds.height * 0.5)
        //밑에서 등장해서 왼쪽으로 사라짐
        .transition(.asymmetric(insertion: AnyTransition.move(edge: .bottom),
                                removal: AnyTransition.opacity.animation(.easeIn))
        )
        .animation(.easeIn)
}

 

읽어주셔서 감사합니다🤟