I would like to extract the velocity of a DragGesture to use for the initialVelocity parameter of a spring animation. I am trying to create a movable card that has a responsive spring animation like that found in the Apple Maps app.
I have tried calculating velocity by dividing the height of the drag translation by the total time elapsed of the drag gesture.
v_abs = abs(Double(drag.translation.height / CGFloat(drag.time.timeIntervalSinceNow)))
The problem is that when a user begins a drag they may slow down the drag before flicking and releasing, which causes the velocity to be very slow since a long period of time has elapsed. If possible, I'd only like to calculate velocity using data from the final milliseconds of the drag gesture.
I've been able to get a pretty decent drag velocity value by storing the last drag position as a state and then using that to derive a speed value when the onEnded gets called.
struct MyComponent: View {
@State var lastDragPosition: DragGesture.Value?
var body: some View {
VStack{
SomeOtherView()
}.gesture(
DragGesture().onChanged { value in
self.lastDragPosition = value
}
.onEnded { value in
let timeDiff = value.time.timeIntervalSince(self.lastDragPosition!.time)
let speed:CGFloat = CGFloat(value.translation.height - self.lastDragPosition!.translation.height) / CGFloat(timeDiff)
if(speed > 500) {
//Do Something
}
}
)
}
}
You can compute the implied velocity without keeping intermediate state simply by using the predictedEndLocation
already supplied by the DragGesture.Value
:
DragGesture()
.onChanged { value in
// Do something
}
.onEnded { value in
let velocity = CGSize(
width: value.predictedEndLocation.x - value.location.x,
height: value.predictedEndLocation.y - value.location.y
)
// Example
if velocity.height > 500.0 {
// Moving down fast
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With