
애니메이션은 그 자체로 자연스러운 효과를 주지만, 단순히 나타나고 사라지는(Fade-in/out) 방식은 자칫 사용자의 시선 흐름을 툭 끊어버릴 수도 있다.
단순히 화면을 교체하는 게 아니라 화면의 형태를 유지하면서 자연스럽게 사용자의 시선을 가이드 한다면 사용자에게 '연속적인 경험'을 줄 수 있을 것이다.
그리고 그것을 MatchedGeometryEffect가 도와줄 것이다.
핵심 원리
딱 두 가지만 알면 된다.
@Namespace : 애니메이션이 일어날 공유 공간을 만든다. 같은 공간 안에 있는 이름표들끼리는 상대적인 위치 좌표를 계산할 수 있게 된다.
matchedGeometryEffect() : 연결하고 싶은 두 뷰에 똑같은 id를 붙여준다.
// 1. 공간을 만들고
@Namespace private var animationSpace
// 2. 출발지와 도착지에 같은 이름표를 붙인다
.matchedGeometryEffect(id: "uniqueID", in: animationSpace)
이렇게 적용하면 같은 공간안에 있는 두 뷰가 애니메이션으로 전환되는 찰나에, 실제로 뷰가 이동되는 느낌을 주게 된다.
원리는 A뷰 -> B뷰로 전환될 때 두 뷰 사이의 거리와 크기 차이를 SwiftUI가 수학적으로 계산해서 그 찰나를 계속해서 메꿔주는 것이다.
즉, matchedGeometryEffect는 뷰를 실제로 옮기는 게 아니라, 두 뷰 사이의 거리와 크기 차이를 보간(Interpolate)해서 눈속임을 하는 기술이다.
예제 1 : 카테고리 바 이동
import SwiftUI
struct CategoryMenu: View {
@Namespace private var namespace // 1. 공간을 만들고
@State private var selected = "A"
let menus = ["A", "B", "C"]
var body: some View {
HStack(spacing: 30) {
ForEach(menus, id: \.self) { menu in
Text(menu)
.padding(10)
.background {
if selected == menu {
Capsule()
.fill(.blue.opacity(0.2))
// 2. 출발지와 도착지에 같은 이름표를 붙인다
.matchedGeometryEffect(id: "background", in: namespace)
}
}
.onTapGesture {
withAnimation { selected = menu }
}
}
}
}
}
비교 영상
왼쪽이 matchedGeometryEffect를 사용하지 않은거고
오른쪽이 사용한 것이다.
예제 2 : 썸네일 확대
struct HeroAnimation: View {
@Namespace private var namespace // 1. 공간을 만들고
@State private var isFull = false
var body: some View {
VStack {
if !isFull {
// 작은 썸네일
RoundedRectangle(cornerRadius: 20)
// 2. 출발지와 도착지에 같은 이름표를 붙인다
.matchedGeometryEffect(id: "card", in: namespace)
.frame(width: 100, height: 100)
} else {
// 전체 화면
RoundedRectangle(cornerRadius: 0)
// 2. 출발지와 도착지에 같은 이름표를 붙인다
.matchedGeometryEffect(id: "card", in: namespace)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
.onTapGesture {
withAnimation { isFull.toggle() }
}
}
}
비교 영상
왼쪽이 matchedGeometryEffect를 사용하지 않은거고
오른쪽이 사용한 것이다.
마무리
matchedGeometryEffect 를 이용한다면 뷰가 전환될 때 사용자에게 '연속적인' 경험을 아주 간편하게 줄 수 있다는 점을 깨달았다.
이런 경험 하나 하나가 축적된다면 사용자에게 편안함을 줄 수 있지 않을까 생각한다.
그리고 이름에는 'Geometry'가 붙고 이 뜻은 '기하학'이며, 공식 홈페이지에는 '보간'이라는 수학적 개념이 나오면서 왜 이런식으로 네이밍을 했는지 원리와 엮어서 보다보니 퍼즐 맞추는 것처럼 이해가 되었다. 앞으로도 이런 네이밍과 개념, 원리 등을 엮어서 볼 수 있는 시선을 가진다면 학습 능률이 올라갈 수 있겠다는 생각이 들었다.
🍎 참고