Neoself의 기술 블로그

PhaseAnimator, Keyframes으로 고급 애니메이션 구현하기 본문

개발지식 정리/Swift

PhaseAnimator, Keyframes으로 고급 애니메이션 구현하기

Neoself 2024. 10. 16. 11:22

이 글은 Apple Developer 유튜브 채널에 있는 "SwiftUI에서 고급 애니메이션 사용하기" 영상의 내용을 정리한 게시글입니다.

https://www.youtube.com/watch?v=NFmQjc7ia4Y

Apple의 SwiftUI에서는 고급 애니메이션을 위해 Animation Phases와 Keyframes 기능을 제공하고 있습니다. 각 기능들을 예시와 함께 설명드리겠습니다.

 

Animation Phases

위 기능은 연속된 애니메이션에 적합한 기능으로, phaseAnimator 뷰 수정자를 사용해 구현할 수 있습니다. 해당 뷰 수정자를 통해 각 단계를 정의하는 일련의 상태를 제공하면, SwiftUI는 자동으로 각 상태 사이를 애니메이팅하게 됩니다.

 

예시

.phaseAnimator([false, true]) { content, phase in
    content
        .opacity(phase ? 1.0 : 0.5)
} animation: { phase in
    .easeInOut(duration: 1.0)
}

위 예제의 경우, true와 false 두개 페이즈를 정의하고 있습니다.

여기서 SwiftUI는 뷰 생성시 false 페이즈로 시작, true 페이즈로 애니메이팅을 진행한 후, 위 과정을 반복하게 됩니다. 필수는 아니지만, animation 클로저를 뒤에 붙일 경우, 애니메이션 유형을 기본 spring 애니메이션에서 변경할 수 있습니다.

 

여기서 열거형 구조를 같이 활용할 경우, 더 복잡한 애니메이션 정의가 가능해집니다.

enum Phase: CaseIterable {
    case initial
    case move
    case scale
    
    var verticalOffset: Double {
        switch self {
        case .initial: return 0
        case .move, .scale: return -64
        }
    }
    
    var scale: Double {
        // 각 단계별 scale 값 정의
    }
    
    var foregroundStyle: Color {
        // 각 단계별 foregroundStyle 정의
    }
}

ReactionView()
    .phaseAnimator(
        Phase.allCases,
        trigger: reactionCount
    ) { content, phase in
        content
            .scaleEffect(phase.scale)
            .offset(y: phase.verticalOffset)
            .foregroundStyle(phase.foregroundStyle)
    } animation: { phase in
        switch phase {
        case .initial: .smooth
        case .move: .easeInOut(duration: 0.3)
        case .scale: .spring(duration: 0.3, bounce: 0.7)
        }
    }

여기서 주목해야할 점은 phaseAnimator 수정자에 트리거값이 추가되었다는 점인데요. 트리거값이 추가되면서 해당 수정자는 변경값을 관찰하게 됩니다. 이로써 주어진 트리거값이 변경될 경우, 지정된 Phase로 애니메이팅이 시작됩니다. 

animation 뷰 수정자에서 전달받은 phase 인자값을 활용해 각 페이즈마다 다른 애니메이션 유형을 지정한 것도 확인할 수 있습니다.

 

다음은 Keyframe 기능입니다.

 

Keyframe

위 기능은 animation phase와 달리 사전에 정의된 애니메이션으로 재생 가능한 비디오 클립에 가깝습니다. 

애플 디벨로퍼 유튜브 영상 스크린캡처본

Keyframe은 위 사진과 같이 여러가지 효과를 각기 다른 시점에 배치할 수 있기에 더 강력한 제어를 제공합니다. 하지만 모든 프레임마다 뷰가 업데이트 되기에 리소스 사용량이 높으며, animation phase와 달리 자연스러운 리타겟이 불가능합니다. 즉 유동적, 상호작용형 UI가 필요한 상황에서는 적합하지 않습니다.

 

Keyframe의 유형은 아래와 같이 정리해볼 수 있습니다.

 

  • LinearKeyframe: 이전 키프레임의 벡터 공간을 선형으로 보간합니다.
  • SpringKeyframe: 스프링 효과를 사용하여 자연스러운 움직임을 만듭니다.
  • CubicKeyframe: 베지어 곡선을 사용하며, 여러 개를 조합하면 캣멀롬 스플라인과 유사한 부드러운 곡선을 만들 수 있습니다.
  • MoveKeyframe: 보간 없이 즉시 값을 변경합니다.

결론

SwiftUI의 Animation Phases와 Keyframes는 복잡하고 세밀한 애니메이션을 구현할 수 있는 강력한 도구입니다. Animation Phases는 연속적이고 반복적인 애니메이션에 적합하며, Keyframes는 더욱 정교한 제어가 필요한 애니메이션에 사용됩니다.

 

감사합니다.