Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Advanced)

2. AnyTransition Custom / 트랜지션 커스텀

by Toughie 2023. 6. 19.

🦁AnyTransition Custom / 트랜지션 커스텀🦁

뷰 전환을 부드럽게 할 때 사용하는 transition을 커스텀해보자.

슉 슈슉

AnyTransition

애니메이션과 함께 뷰 전환을 처리하고 커스텀 전환 효과를 만들 때 사용됨

 

기본 제공 전환효과들

for custom


View

struct AnyTransitionPrac: View {
    
    @State private var showRectangle: Bool = false
    
    var body: some View {
        VStack {
            Spacer()
            if showRectangle {
                RoundedRectangle(cornerRadius: 25)
                    .fill(LinearGradient(colors: [Color.blue, Color.green], startPoint: .topLeading, endPoint: .bottomTrailing))
                    .frame(width: 300, height:300)
                    
                    //edge에서 등장, 사라짐
                    .transition(.move(edge: .leading))
                    
                    //스케일 이펙트를 통해 등장, 사라짐
                    .transition(AnyTransition.scale.animation(.easeInOut))
                    
                    //AnyTransition extension을 통한 타입 계산 속성
                    .transition(AnyTransition.rotating)
                    
                    //AnyTransition extension을 통한 타입 메서드
                    .transition(.rotating)
                    .transition(.rotating(amount: 180))
                    
                    //.asymmetric을 통해 등장, 사라짐 다른 애니메이션
                    .transition(.asymmetric(insertion: .rotating(amount: 180), removal: .move(edge: .trailing)))
                    
                    // extension
                    .transition(.rotateOn)
            }

            Spacer()
            
            Text("Tap")
                .defaultButtonFormatting()
                .padding(.horizontal,50)
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 0.7)) {
                        showRectangle.toggle()
                    }
                }
        }
    }
}

ViewModifier

struct RotateViewModifier: ViewModifier {
    
    let rotation: Double
    
    func body(content: Content) -> some View {
        content
        	//memberwise initializer 통해 rotation 값 받아옴
            .rotationEffect(Angle(degrees: rotation))
            .offset(
            	//rotation 값이 0 이 아닌 경우 x축은 화면 너비만큼, y축은 화면 높이만큼 offset 조정
                // -> 우측 하단, bottom trailing에서 올라오는 효과가 됨
                x: rotation != 0 ? UIScreen.main.bounds.width : 0,
                y: rotation != 0 ? UIScreen.main.bounds.height : 0)
    }
}

Extension

extension AnyTransition {
    //type computed property 
    //이미 AnyTransition의 확장이기 때문에 return AnyTransition은 생략 가능
    //즉 modifier(active ~~)도 가능
    static var rotating: AnyTransition {
        return AnyTransition.modifier(active: RotateViewModifier(rotation: 180), identity: RotateViewModifier(rotation: 0))
    }
    
    //type method
     /*
     active
     전환 중에 적용되는 변환을 정의(전환 시작 상태)
     
     identity
     전환의 끝 상태에서 적용되는 변환 정의 (전환 완료 후 뷰 최종 상태)
     */
    static func rotating(amount: Double) -> AnyTransition {
        return AnyTransition.modifier(active: RotateViewModifier(rotation: amount), identity: RotateViewModifier(rotation: 0))
    }
    
    static var rotateOn: AnyTransition {
    //return AnyTransition을 생략한 경우
        asymmetric(
            insertion: .rotating,
            removal: .rotating(amount: 100)
        )
    }
}