안녕하세요! 피피아노입니다 🎵
이번 포스팅에서는 SwiftUI에서 뷰를 애니메이션 하는 것과 앱 내에서의 전환에 대한 것을 한번 정리를 해보려고 합니다.
그럼 바로 시작하겠습니다!
암묵적 애니메이션
SwiftUI에 뷰는 크기, 색상, 회전 각도, 불투명도 등 뷰의 외형을 제어하는 프로퍼티들을 가지고 있습니다. 이런 종류의 프로퍼티는 A라는 상태에서 B라는 상태로 바뀌는 것을 애니메이션 되게 할 수 있습니다.
이러한 상태 변화를 할 때 애니메이션이 나타나게 하는 방법 중 하나는 animation() 수정자를 사용하는 것입니다. 이것을 암묵적 애니메이션(implicit animation)이라고 부르는데, 애니메이션 수정자 앞에 있는 모든 수정자를 암묵적으로 애니메이션 되도록 만들어줍니다.
애니메이션 효과를 보기 위해 프로젝트 파일에 Button 뷰를 추가하고, 버튼을 터치할 때마다 90도씩 회전하도록 소스를 작성해 보았습니다.
프리뷰를 활용해서 테스트를 해보면 애니메이션 버튼을 클릭할 때마다 90도씩 Button 뷰가 회전하는 것을 확인할 수 있습니다.
해당 소스에서
self.rotation = (slef.rotation < 360 ? self.rotation + 90 : 0)
이 부분에서 90을 360으로 바꾸면 한 바퀴 회전하는 것 역시 확인할 수 있습니다.
만약에 회전하는 속도가 너무 빠르거나 너무 느려서 속도에 변화를 주고 싶어 진다면
애니메이션 타이밍을 제어하는 애니메이션 커브를 가진 animation() 수정자를 추가하면 됩니다.
저는 linear 애니메이션 커브를 넣어줬는데 이렇게 되면 위에처럼 지정된 시간 동안 일정한 속도로 애니메이션을 수행하게 됩니다.
- .linear: 지정된 시간 동안 일정한 속도로 애니메이션을 수행
- .easeOut: 빠른 속도로 애니메이션을 시작하고 애니메이션 끝에 다다를수록 점점 느려짐
- .easeIn: 느린 속도로 애니메이션을 시작하고 애니메이션 끝에 다다를수록 점점 빨라짐
- .easeInOut: 느린 속도로 애니메이션을 시작하고 점점 속도를 올리다가 애니메이션의 끝에 다다를수록 다시 속도가 느려짐
여기서 value 매개변수는 애니메이션을 제어하는 데 사용되는 값을 애니메이션 함수에게 알려주는 역할을 합니다.
Spring() 수정자를 사용하면 스프링 효과도 적용해 줄 수 있습니다.
이렇게 하면 설정해 준 값에 따라서 회전 효과가 범위를 살짝 넘어갔다가 다시 돌아오는 효과가 나타납니다.
애니메이션 반복
애니메이션들은 기본적으로 한 번만 수행하기 됩니다. 하지만 기본적으로 한 번만 수행한다고 해서 반복이 안 되는 것이 아닙니다.
아래처럼 소스를 수정해 주면 지정된 횟수만큼 애니메이션을 반복하도록 할 수 있습니다.
.animaation(Animation.linear(duration: 1).repeatCount(5), value: rotation)
이렇게 소스를 작성해 주면 애니메이션이 반복될 때마다 뷰가 원래 상태로 되돌아가도록 역으로 애니메이션이 수행될 것입니다.
하지만 모든 상황에서 애니메이션이 원래 상태로 되돌아가는 것을 기다릴 수 없겠죠? 그럴 때를 위해서 뷰의 원래 모양을 즉시 되돌릴 수 있는데 그럴 때는 autoreverses 매개변수를 false로 설정해 주면 원래 상태로 즉시 되돌아가게 됩니다!
.animation(Animation.linear(duration: 1).repeatCount(10, autoreverses: false), value: rotation)
그리고 만약에 애니메이션을 특정 값만큼만 반복하는 게 아니라 무한 반복하도록 하고 싶다면 repeatForever() 수정자를 수정해주면 됩니다.
.repeatForever(autoreverses: true))
명시적 애니메이션
SwiftUI는 withAnimation() 클로저를 사용하여 구현되는 명시적 애니메이션(explicit animation)이라는 방법도 제공합니다.
명시적 애니메이션을 사용하게 되면 암묵적 애니메이션과 반대로 withAnimation() 클로저 내에서 변경된 프로퍼티만 애니메이션이 구현되게 됩니다. 이 내용은 앞 내용을 알고 있다면 간단한 내용이니까 구현 모습은 스킵하고 소스와 설명만 올려두겠습니다!
struct ContentView: View {
@State private var scale: CGFloat = 1
@State private var rotation: Double = 0
var body: some View {
Button(action: {
withAnimation(.linear(duration: 2)) {
self.rotation = (self.rotation < 360 ? self.rotation + 90 : 0)
self.scale = (self.scale < 4.2 ? self.scale + 0.5 : 1)
}
}) {
Text("애니메이션 버튼")
.rotationEffect(.degrees(rotation))
.scaleEffect(scale)
}
}
}
이 소스에서 버튼을 클릭할 때 텍스트가 회전하고 크기가 변하는 애니메이션을 구현하고 있는 것을 확인할 수 있습니다.
먼저 @State로 선언된 scale 변수는 텍스트의 크기를 조절하며, 기본값으로 1이 설정되어 있습니다. rotation 변수는 텍스트가 회전할 각도를 나타내며, 0도에서 시작해 버튼 클릭 시 90도씩 회전하게 됩니다.
사용자가 버튼을 클릭하면, withAnimation을 사용해 애니메이션 효과가 2초 동안 선형적으로 발생합니다. 이 때, rotation 값은 90도씩 증가하다가 360도를 넘으면 다시 0도로 초기화됩니다. 동시에 scale 값은 0.5씩 커지며, 최대 4.2배까지 커졌다가 다시 1로 돌아옵니다. 이 두 가지 값은 rotationEffect와 scaleEffect를 통해 텍스트에 적용되어, 클릭할 때마다 텍스트가 회전하면서 커지는 효과를 시각적으로 보여줍니다.
오늘은 여기까지 :)
'Apple > SwiftUI' 카테고리의 다른 글
[SwiftUI] SwiftUI와 UIKit 통합하기 (2/2) (2) | 2024.09.21 |
---|---|
[SwiftUI] SwiftUI와 UIKit 통합하기 (1/2) (5) | 2024.09.14 |
[SwiftUI] @AppStorage와 @SceneStorage 프로퍼티 래퍼 이해하기 (6) | 2024.09.11 |
[SwiftUI] Property Wrapper 알아보기 (0) | 2024.07.29 |
[SwiftUI] AVFoundation 톺아보기 (2) | 2024.07.15 |