Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 스위프트
- uitableview
- UICollectionView
- tableView
- collectionview
- MVVM
- Observable
- Clean Code
- 리펙터링
- 리펙토링
- Xcode
- SWIFT
- 리팩토링
- combine
- map
- Protocol
- swift documentation
- clean architecture
- Refactoring
- rxswift
- uiscrollview
- Human interface guide
- swiftUI
- UITextView
- 클린 코드
- RxCocoa
- 애니메이션
- HIG
- ribs
- ios
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - SwiftUI] GeometryEffect 사용 방법 (움직이는 애니메이션) 본문
GeometryEffect 개념
- 위치를 변경해주는 이펙트 형태를 갖고있는 프로토콜
- effectValue 메소드에서 CGAffineTransform과 같은 위치 관련 변환하는 코드를 넣고 리턴
- GeometryEffect라는 프로토콜을 준수하는 struct를 만들고, 사용하는쪽에서 .modifier()와 같은 곳에 주입하여 사용
- main thread에서 위치를 보간할때마다(=애니메이션이 적용될때마다) 계속 불리는 메소드가 effectValue
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol GeometryEffect : Animatable, ViewModifier where Self.Body == Never {
/// Returns the current value of the effect.
func effectValue(size: CGSize) -> ProjectionTransform
}
사용 방법
* 코드는 이곳을 참고
예시 코드) 버튼을 눌렀을 때 따봉 애니메이션 넣기
- 사용하는쪽에서 modifier에 LikeEffect라는, GeometryEffect프로토콜을 준수하고 있는 인스턴스를 삽입하여 사용
- LikeEffect에는 offset 인수로 likes라는 값을 삽입
- offset에 likes가 들어갈때 LikeEffect 내부적으로는 보간
- 보간 형태
- 0이 주입되면 0.0, 0.1, 0.2, ... 1.0
- 1이 주입하면, 1.0, 1.1, 1.2, ... 2.0
- 2가 주입되면, 2.0, 2.1, 2.2, ... 3.0
struct ContentView: View {
@State var likes = 0.0
var body: some View {
HStack {
Text("likes: \(Int(likes))")
.frame(width: 150, alignment: .leading)
.padding()
Button(
action: { withAnimation(.spring()) { self.likes += 1 } },
label: {
HStack {
Text("like more")
Image(systemName: "hand.thumbsup")
.modifier(LikeEffect(offset: likes)) // <-
}
}
)
}
}
}
- LikeEffect 구현
- GeometryEffect 준수하고 effectValue(size:) 메소드 구현
struct LikeEffect: GeometryEffect {
var offset: Double
func effectValue(size: CGSize) -> ProjectionTransform {
/// offset에 1이 들어온 경우: 0.0, 0.1, 0.2, 0.3 ... 1.0
/// offset에 2가 들어온 경우: 1.0, 1.1, 1.2, 1.3 ... 2.0
// TODO
}
}
- GeometryEffect는 내부적으로 Animatable을 준수하고 있으므로, 애니메이션 효과가 동작하려면 animatableData도 구현 필요
- Animatable, animatableData 관련 개념은 이전 포스팅 글 참고
struct LikeEffect: GeometryEffect {
var offset: Double
// 추가
var animatableData: Double {
get { offset }
set { offset = newValue }
}
func effectValue(size: CGSize) -> ProjectionTransform {
/// offset에 1이 들어온 경우: 0.0, 0.1, 0.2, 0.3 ... 1.0
/// offset에 2가 들어온 경우: 1.0, 1.1, 1.2, 1.3 ... 2.0
// TODO
}
}
- effectValue 메소드 구현
func effectValue(size: CGSize) -> ProjectionTransform {
/// offset에 1이 들어온 경우: 0.0, 0.1, 0.2, 0.3 ... 1.0
/// offset에 2가 들어온 경우: 1.0, 1.1, 1.2, 1.3 ... 2.0
/// 0.0 ~ 1.0까지의 값: 0.0, 0.1, ... 0.9, 0.8, 0.9, 1.0
let reducedValue = offset - floor(offset)
print(offset, reducedValue)
/// 움직인 각도
let value = 1.0-(cos(2*reducedValue*Double.pi)+1)/2
let angle = CGFloat(Double.pi*value*0.3)
let translation = CGFloat(20*value)
let scaleFactor = CGFloat(1+value)
let affineTransform = CGAffineTransform(translationX: size.width*0.5, y: size.height*0.5)
.rotated(by: CGFloat(angle))
.translatedBy(x: -size.width*0.5+translation, y: -size.height*0.5-translation)
.scaledBy(x: scaleFactor, y: scaleFactor)
return ProjectionTransform(affineTransform)
}
* 전체 코드: https://github.com/JK0369/ExGeometryEffect-SwiftUI
* 참고
https://nerdyak.tech/development/2019/08/29/tweaking-animations-with-GeometryEffect.html
https://developer.apple.com/documentation/swiftui/geometryeffect
'iOS 기본 (SwiftUI)' 카테고리의 다른 글
Comments