swift에서 애니메이션을 만들기 위해서는 withAnimation(Animation, Closure) 함수를 사용해야 합니다. 이 함수는 애니메이션을 수행하게 하고 결과를 반환합니다. 첫번째 인수로 들어가는 값은 어떤 타입의 애니메이션을 사용할지를 결정하는 것입니다. 만약 무시하려면 default(기본값)으로 설정하면 됩니다. 두번째 인수로 들어가는 것은 Closure로 우리가 애니메이션을 시키고 싶은 내용을 정의하는 곳입니다.
animation을 이용하면 effect을 사용하여 애니메이션을 시킬 수 있습니다.
animation는 default, easeIn, easeInOut, easeOut, linear 이 있으며 nil을 넣어서 바로 중단시킬수도 있습니다.
아래 코드에서는 .scaleEffect(boxScale)을 이용하여 boxScale 값에 따라서 상자의 크기를 키우는 것입니다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.default) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
Linear
다음은 linear을 사용하여 애니메이션 효과를 사용한 코드다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.linear) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
다음은 linear로 애니메이션을 지정하되 5초에 거쳐서 애니메이션이 작동하도록 만든 것이다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.linear(duration: 5)) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
다음으로는 다음처럼 custom animation을 만들어서 내가 원하는 애니메이션 효과를 직접 만들 수 있다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
let animation = Animation.bouncy
.delay(1)
.speed(2)
.repeatCount(3)
withAnimation(animation) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
interpolatingSpring
damped(감쇠된) 스프링 모델을 사용하여 애니메이션 속성의 [from, to] 범위 내에서 보간하는 데 사용되는 [0, 1] 범위의 값을 생성하는 보간 스프링 애니메이션이다. 각 애니메이션의 효과를 추가하여 겹치는 애니메이션의 속도를 유지한다.
mass: 값이 커지면 그만큼 진동시간이 증가하게 된다 (무거운 물체가 달려있을수록 스프링이 진동하는 시간이 길어지고 느려지듯이)
stiffness: 애니메이션의 빠르기를 의미한다.
damping: 값이 커지면 스프링 애니메이션의 탄성이 떨어진다 (스프링 애니메이션의 탄성마찰력에 해당한다)
initialVelocity: 애니메이션이 변경되는 속도를 의미한다 ( [0, 1] 사이의 값에 해당한다 )
다음은 무한반복으로 앞뒤로 왔다갔다하는 애니메이션을 만든 것이다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
let animation = Animation.interpolatingSpring(mass: 0.15, stiffness: 0.8, damping: 0.5, initialVelocity: 5)
.speed(5)
.repeatForever()
withAnimation(animation) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
EaseIn
다음은 easeIn을 사용하여 2초동안 애니메이션이 작동하도록 설정한 코드다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
@State private var roundCorners: Bool = false
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.cornerRadius(roundCorners ? 15 : 0)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.easeIn(duration: 2)) {
boxScale = 2
roundCorners = true
}
}
}.padding()
}
}
#Preview {
ContentView()
}
easeInOut
다음은 easeInOut을 사용하여 2초동안 애니메이션이 작동하도록 설정한 코드다.
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
@State private var roundCorners: Bool = false
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.cornerRadius(roundCorners ? 15 : 0)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.easeInOut(duration: 2)) {
boxScale = 2
roundCorners = true
}
}
}.padding()
}
}
#Preview {
ContentView()
}
아래는 2개의 애니메이션이 동작하도록 설정되어 있다. easeOut과 linear의 조합
import SwiftUI
struct ContentView: View {
@State private var boxScale: CGFloat = 1
@State private var roundCorners: Bool = false
var body: some View {
VStack {
HStack {
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50)
.cornerRadius(roundCorners ? 15 : 0)
.scaleEffect(boxScale)
}.frame(width: 250, height: 120)
Button("Animate") {
withAnimation(.easeOut) {
roundCorners = true
}
withAnimation(.linear) {
boxScale = 2
}
}
}.padding()
}
}
#Preview {
ContentView()
}
'SwiftUI' 카테고리의 다른 글
Image Renderer (0) | 2023.11.07 |
---|---|
Effect (scaleEffect, rotation3DEffect) (0) | 2023.11.06 |
Gradient (0) | 2023.11.06 |
Extensions (0) | 2023.11.06 |
Swift Protocols (Equatable, Comparable, Hashable, Numeric, CaseIterable) (0) | 2023.11.05 |