결과물🤟🏻:
아이콘 전환시 부드럽게 넘어가는 느낌의 애니메이션
이번 애니메이션을 학습하게된 계기 🔫:
이전 포스팅에서 다이나믹 아일랜드와 이미지가 합쳐지는 듯한 효과를 학습했었다.
https://april21st.tistory.com/185
Kavsoft채널에서 Metaball Effect로 소개된 애니메이션이며 Cavas shape과 blur효과를 적절히 사용한 것이다. Metaball Effect와 비슷한 방식으로 Blur효과를 적절히 사용하여 아이콘 전환 애니메이션을 학습 및 탐구
Reference ✂️ :
https://www.youtube.com/watch?v=HVNxfI8XYMw
과정 🎩:
Step 1. 아이콘(이미지) View 설정
struct ResolvedImage: View {
@Binding var currentImage: CustomShape
var body: some View {
Image(systemName: currentImage.rawValue)
.font(.system(size:200))
.animation(.interactiveSpring(response: 0.7, dampingFraction: 0.8, blendDuration: 0.8), value: currentImage)
.frame(width: 300, height: 300)
}
}
아이콘들을 표시할 View를 struct로 구성하며 이미지의 Modifier를 구성
animation의 Spring은 피사체가 이동 후 반동을 주는 효과를 적용시킬 수 있다.
Spring 애니메이션을 약간 딱딱한 느낌으로 사용한 것이 interativeSpring이다.
Animate 버튼 클릭시 미적용
Update 버튼 클릭시 애니메이션 적용
(response: 반응속도, dampingFriction: 제동력, blendDuration: 두 개 이상의 SpringAnimation을 적용했을 때의 혼합 정도)
// CustomSahpe Model
import SwiftUI
enum CustomShape: String, CaseIterable{
case cloud = "cloud.rain.fill"
case bubble = "bubble.left.and.bubble.right.fill"
case map = "map.fill"
case square_1 = "square.fill.on.square.fill"
case bell = "bell.and.waves.left.and.right.fill"
case square = "square.fill.on.circle.fill"
}
CustomShape는 열거형(enum)으로 모델구성을한다. 화면 전환시 보여질 아이콘들을 열거하였다.
Step 2. MainView에 보여질 아이콘(이미지) 설정
Canvas{context, size in
// MARK: Morphing
context.addFilter(.alphaThreshold(min: 0.3))
// MARK: This Value Plays Major Role in the Morphing Animation
// MARK: For Reverse Animation
context.addFilter(.blur(radius: blurRadius >= 20 ? 20 - (blurRadius - 20) : blurRadius))
// MARK: Draw Inside Layer
context.drawLayer { ctx in
if let resolvedImage = context.resolveSymbol(id: 1){
ctx.draw(resolvedImage, at: CGPoint(x: size.width / 2, y: size.height / 2), anchor: .center)
}
}
} symbols: {
// MARK: Giving Images With ID
ResolvedImage(currentImage: $currentImage)
.tag(1)
}
Canvas를 활용하여 ResolvedImage를 그려준다. 또한 blurRadius를 40으로 설정하여 1에서 시작하여 20까지는 사라지는 느낌의 효과 21부터 40까지는 다시 생성되는 효과를 줄 수 있도록 한다.
// MARK: Animation will not Work in the Convas
.onReceive(Timer.publish(every: 0.007, on: .main, in: .common).autoconnect()) { _ in
if animateMorph {
if blurRadius <= 40 {
blurRadius += 0.5
if blurRadius.rounded() == 20 {
// MARK: Change Of Next Image Goes Here
currentImage = pickerImage
}
}
if blurRadius.rounded() == 40 {
// MARK: End Animation And Reset the Blur Radius to Zero
animateMorph = false
blurRadius = 0
}
}
}
Step 3. 아이콘 전환 선택 활성화
//MARK: Segmented Picker
Picker("", selection: $pickerImage) {
ForEach(CustomShape.allCases, id: \.rawValue) { shape in
Image(systemName: shape.rawValue)
.tag(shape)
}
}
.pickerStyle(.segmented)
// MARK: Avoid Tap Until The Current Animation is Finished
.overlay(content: {
Rectangle()
.fill(.primary)
.opacity(animateMorph ? 0.05 : 0)
})
.padding(15)
.padding(.top, -50)
// MARK: When Ever picker Image Changes
.onChange(of: pickerImage) { newValue in
animateMorph = true
}
Picker를 사용하여 아이콘(이미지)를 선택할 수 있도록 설정 또한 Retangle을 overlay로 설정하여 아이콘 전환 중에 다른 버튼을 클릭할 수 없도록 방지하며 아이콘 선택창이 활성화된 것을 사용자가 인식할 수 있도록 한다.
Step 4. 토글버튼을 사용하여 아이콘 화면에 다른 이미지(사진)을 표시할 수 있는 효과 설정
Toggle("Turn Off Image Morph", isOn: $turnOffImageMorph)
.fontWeight(.semibold)
.padding(.horizontal, 15)
.padding(.top, 10)
turnOffImageMorph가 true인 경우 다른 이미지(사진)이 mask된다.
Step 5. 이미지(사진)을 설정
GeometryReader { proxy in
let size = proxy.size
Image("pic")
.resizable()
.aspectRatio(contentMode: .fill)
.offset(y: 50)
.frame(width: size.width, height: size.height)
.clipped()
.overlay(content: {
Rectangle()
.fill(.white)
.opacity(turnOffImageMorph ? 1: 0)
})
.mask{
...
}
}
turnOfImageMorph 토글을 활용하여 투명도를 1과 0으로 설정하여 이미지 노출을 설정한다.
.mask 블럭안에는 Canvas블럭을 넣어준다.
mask는 ZStack처럼 그림위에 아이콘을 입힐 수 있도록 활용하는 것이다.
마스크를 활용하면 별점 효과를 효과적으로 만들 수 있다. (서근 개발 노트 참고)
https://seons-dev.tistory.com/entry/SwiftUI-Mask
'IOS' 카테고리의 다른 글
SwiftUI Curved Custom Tab Bar - Kavsoft (iOS 인터렉티브 애니메이션) (0) | 2023.08.08 |
---|---|
SwiftUI Metaball Animation - Kavsoft (iOS 인터렉티브 애니메이션) (0) | 2023.08.01 |
SwiftUI, 인터렉티브 다이나믹 아일랜드 스크롤 애니메이션 만들기[1] (0) | 2023.07.10 |
SwiftUI Blur 효과/ UIBlurEffect (0) | 2023.07.03 |
Playground 코딩 배우기 2 총 개수 모으기 (0) | 2023.05.15 |