드래그(Pan, drag) 동작에서 관성유지에 대한 수학적 접근
패닝이벤트 처리를 위한 수식
-상식으로도해결가능하지만-
입력종료시에 속도(v0)일 때,
시간(t1)동안 등감속하여, 멈추는 경우
이동거리는 (1/2)*v0*t1
여기서 가속도는 v0->0 으로 v0와 t1 으로 표현 가능하다.
문장으로 정리하면,
등감속 이동거리는
입력종료시의 속도(v0)로 감속시간(t1) 동안
이동한 거리의 절반이다.
아래 이미지는 수식으로 증명한 과정.
Swift code: Panning -> Moving with a Moment
@objc func panGestureAction(_ gesture: UIPanGestureRecognizer!) {
print("\(#function) v:\(gesture.velocity(in: self.view))")
guard gesture.state != .began else {
gesture.setTranslation(CGPoint.zero, in: self.view)
return
}
// 드래그 시작 후 기준좌표계에서 이동 거리
let movingPoint: CGPoint = gesture.translation(in: self.view)
if gesture.state == .ended {
// 애니메이션 듀레이션
let panMomentDuration: TimeInterval = 0.15
// 시작속도 v0
let velocity_v0 = gesture.velocity(in: self.view)
// 듀레이션 t1
let duration_t1 = CGFloat(panMomentDuration)
// 관성이동거리
let momentDistance = velocity_v0.scaling(duration_t1/2.0)
// 최종 변경된 위치
let endCenter = self.playerContainerView.center
.adding(distance: movingPoint)
.adding(distance: momentDistance)
UIView.animate(withDuration: panMomentDuration,
delay: 0.0,
options: [.beginFromCurrentState,
.curveEaseOut],
animations: {
self.playerContainerView.transform = .identity
self.playerContainerView.center = endCenter
},
completion: nil)
} else {
let movingTransform = CGAffineTransform(translationX: movingPoint.x,
y: movingPoint.y)
self.playerContainerView.transform = movingTransform
}
}