⭐️DragGestrue() 드래그 제스쳐⭐️
손가락으로 드래그했을 때 다양한 효과를 주는 법을 알아보자.
상하좌우 이동도 가능하고, 이에 맞춰 크기 변화도 줄 수 있고 여러 애니메이션 효과를 가미할 수 있다.
1. 좌우 이동 스케일 효과
// Created by Toughie on 2023/05/25.
//
import SwiftUI
struct DragGesturePrac: View {
//초기 오프셋 0에서 시작
@State var offset: CGSize = .zero
var body: some View {
ZStack {
VStack {
Text("\(offset.width)")
Spacer()
}
RoundedRectangle(cornerRadius: 20)
.fill(Color.blue.opacity(0.3))
.frame(width: 300, height: 500)
.offset(offset)
//좌우 드래그 시 스케일을 줄이는 효과
.scaleEffect(getScaleAmount())
//좌우 드래그 시 각도를 기울이는 효과
.rotationEffect(Angle(degrees: getRotationAmount()))
.gesture (
DragGesture()
.onChanged{ value in
withAnimation(.default) {
//드래그 한 만큼 오프셋 변경
offset = value.translation
}
}
.onEnded { value in
// 드래그가 끝났을 때 제자리로 돌아가도록
withAnimation(.spring()) {
offset = .zero
}
}
)
}
}
//드래그 했을 때 얼마나 스케일을 변경할 것인가?
func getScaleAmount() -> CGFloat {
//화면 절반 이상 드래그 하는 경우는 드물기에, 절반까지를 최대로 설정
let max = UIScreen.main.bounds.width / 2
//좌우 상관없이 스케일을 바꾸기에 절대값 사용
let currentAmount = abs(offset.width)
//최대 범위 대비 얼마나 이동했는가?
let percentage = currentAmount / max
//최대 75%까지만 작아지도록
return 1.0 - min(percentage, 0.5) * 0.5
}
//드래그 했을 때 각도를 얼마나 기울일 것인가?
func getRotationAmount() -> Double {
let max = UIScreen.main.bounds.width / 2
let currentAmount = offset.width
let percentage = currentAmount / max
let percentageAsDouble = Double(percentage)
let maxAngle: Double = 10
//최대 10도까지
return percentageAsDouble * maxAngle
}
}
2. 위로 끌어올리는 화면 구현
// Created by Toughie on 2023/05/25.
//
import SwiftUI
struct DragGesturePrac2: View {
@State var startingOffsetY: CGFloat = UIScreen.main.bounds.height * 0.85
@State var currentDragOffsetY: CGFloat = 0
@State var endingOffsetY: CGFloat = 0
var body: some View {
ZStack {
//배경색
Color.blue.ignoresSafeArea().opacity(0.4)
//로그인 뷰 예시
SignUpView()
.offset(y: startingOffsetY)
.offset(y: currentDragOffsetY)
.offset(y: endingOffsetY)
.gesture(
DragGesture()
.onChanged { value in
withAnimation(.spring()) {
currentDragOffsetY = value.translation.height
}
}
.onEnded { value in
withAnimation(.spring()) {
//offset이 -150 미만이면 원래 위치로 돌아가도록
if currentDragOffsetY < -150 {
endingOffsetY = -startingOffsetY
// 위에서 끌어내릴 때, endingOffsetY가 0이 아닌지 확인하고(맨 위에 있을 때 -startingOffsetY임)
// 일정 범위 이상(150) 끌어내렸을 때 원래 위치로 돌아가도록 endingOffsetY를 0으로
} else if endingOffsetY != 0 && currentDragOffsetY > 150 {
endingOffsetY = 0
}
//다음 드래그가 이전 드래그에 영향을 받지 않도록 초기화
currentDragOffsetY = 0
}
}
)
Text("\(currentDragOffsetY)")
}
.ignoresSafeArea(edges: .bottom)
}
}
if currentDragOffsetY < -150 조건이 참이면, endingOffsetY를 -startingOffsetY로 설정하여 뷰를 원래 위치로 이동시킨다.
반대로, if currentDragOffsetY > 150 조건이 참이면, endingOffsetY를 0으로 설정하여 뷰를 초기 위치로 되돌린다.
currentDragOffsetY = 0 코드는 이후에 currentDragOffsetY 값을 초기화하는 역할을 한다.
-> 다음 드래그 제스처가 시작될 때 이전 드래그 제스처의 영향을 받지 않고 새로운 드래그를 시작할 수 있다.
'SwiftUI > SwiftUI(Intermediate)' 카테고리의 다른 글
13. GeometryReader / rotation3DEffect (0) | 2023.05.25 |
---|---|
12. ScrollViewReader 스크롤뷰 리더 (0) | 2023.05.25 |
10. LongPressGesture 길게 누르기 (0) | 2023.05.25 |
9. RotationGesture/effect 회전 애니메이션 (0) | 2023.05.25 |
8. MagnificationGesture (확대/축소) (0) | 2023.05.25 |