본문 바로가기
IT/swift

100 days of SwiftUI - Day33

by 가능성1g 2024. 11. 29.
반응형

애니메이션 더 공부하는 시강!

 

간단한 버튼 애니메이션

//
//  ContentView.swift
//  Animation
//
//  Created by HanTJ on 11/29/24.
//

import SwiftUI

struct ContentView: View {
    @State private var enabled = false
    var body: some View {
        Button("Tap Me") {
            enabled.toggle()
        }
        .frame(width: 200, height: 200)
        .background(enabled ? .blue : .red)
        .animation(.default, value: enabled)
        .foregroundStyle(.white)
        .clipShape(.rect(cornerRadius: enabled ? 60 : 0))
        .animation(.spring(duration: 1, bounce: 0.6), value: enabled)
    }
}

#Preview {
    ContentView()
}

사각형이 버튼을 누르면 각이 둥글어지는데 바운스가 있고 부드럽게 바뀐다. 

 

드래그 애니메이션

//
//  ContentView.swift
//  Animation
//
//  Created by HanTJ on 11/29/24.
//

import SwiftUI

struct ContentView: View {
    @State private var dragAmount = CGSize.zero
    var body: some View {
        LinearGradient(colors: [.yellow, .red], startPoint: .topLeading, endPoint: .bottomTrailing)
            .frame(width: 300, height: 200)
            .clipShape(.rect(cornerRadius: 10))
            .offset(dragAmount)
            .gesture(
                DragGesture()
                    .onChanged { dragAmount = $0.translation }
                    .onEnded { _ in
                        withAnimation(.bouncy) {
                            dragAmount = .zero
                        }
                    }
            )
            .animation(.bouncy, value: dragAmount)
        
    }
}

#Preview {
    ContentView()
}

LinearGradient라는 새로운 뷰 등장! 하지만 직관적으로 선형 그레디언트를 그린다는걸 알수 있음

이미지의 이동 관련 CGSize라는 타입  이용하는건 참조!

드래그를 위해서 gesture 모디파이어를 쓰고, DragGesture 함수를 이용한다. 이벤트 onChaged, onEnded를 이용하면서 값(dragAmount)를 바꿔주어서 애니메이션을 자연스럽게 줄수 있다. 여기에 추가 효과(.bouncy)를 주면 자연스럽게 바운스를 줄수 있다.

 

응용인데 더멋진 예제! 글자별로 애니메이션 주기

//
//  ContentView.swift
//  Animation
//
//  Created by HanTJ on 11/29/24.
//

import SwiftUI

struct ContentView: View {
    let letters = Array("Hello SwiftUI")
    @State private var enabled = false
    @State private var dragAmount = CGSize.zero

    var body: some View {
        HStack(spacing: 0) {
            ForEach(0..<letters.count, id: \.self) { num in
                Text(String(letters[num]))
                    .padding(5)
                    .font(.title)
                    .background(enabled ? .blue : .red)
                    .offset(dragAmount)
                    .animation(.linear.delay(Double(num) / 20), value: dragAmount)
            }
        }
        .gesture(
            DragGesture()
                .onChanged { dragAmount = $0.translation }
                .onEnded { _ in
                    dragAmount = .zero
                    enabled.toggle()
                }
        )
    }
}

#Preview {
    ContentView()
}

ForEach를 이용해서 Text를 한글자씩 쪼개고, 위치(offset)을 줘서 애니메이션을 주는데, delay를 이용해서 꼬리물듯이 움직이게 애니메이션을 완성한다. 

gesture 는 위와 동일 + toggle 로 색변화 추가함

멋있으니 이건 한컷 추가

 

이전에 배운 ViewModifier를 이용해서 커스텀 애니메이션도 선언해놓고 재활용이 가능하다.

//
//  ContentView.swift
//  Animation
//
//  Created by HanTJ on 11/29/24.
//

import SwiftUI

struct CornerRotateModifier: ViewModifier {
    let amount: Double
    let anchor: UnitPoint

    func body(content: Content) -> some View {
        content
            .rotationEffect(.degrees(amount), anchor: anchor)
            .clipped()
    }
}

extension AnyTransition {
    static var pivot: AnyTransition {
        .modifier(
            active: CornerRotateModifier(amount: -90, anchor: .topLeading),
            identity: CornerRotateModifier(amount: 0, anchor: .topLeading)
        )
    }
}

struct ContentView: View {
    @State private var isShowingRed = false

    var body: some View {
        ZStack {
            Rectangle()
                .fill(.blue)
                .frame(width: 200, height: 200)

            if isShowingRed {
                Rectangle()
                    .fill(.red)
                    .frame(width: 200, height: 200)
                    .transition(.pivot) //뷰모디파이어로 추가한 애니메이션
            }
        }
        .onTapGesture {
            withAnimation {
                isShowingRed.toggle()
            }
        }
    }
}

#Preview {
    ContentView()
}

extension 은 AnyTransition을 하면되고, 이용하는 transition에 .이름(pivot)으로 추가한다! 오올!

다른 ViewModifier는 뷰에 .으로 접근해서 바로 함수호출같이 했는데  transition에 속성값으로 넣는건 연구좀 해봐야 겠다..

이 애니메이션은 사각형내에 다른 사각형이 바뀌어 내려오는듯한 모양이다.

 

머리속으로는 이해 하겠는데, 창의적인 모션을 만드라고 하면 힘들듯하다..

하지만 카드 게임 만들때 섞는모습이나 나눠주는건 만들수 있겠다?

반응형