Reputation: 13870
I have followed a tutorial on how to create interactive iOS control center animation using UIViewPropertyAnimator:
http://www.swiftkickmobile.com/building-better-app-animations-swift-uiviewpropertyanimator/
when swiping up or down the bottom menu, after releasing the finger, I want to add pan velocity to UIViewPropertyAnimator
and continue the animation:
popupViewPanned(recognizer:) {
switch recognizer.state {
.
.
.
// after finger released
case .end:
// continue all animations using pan velocity with spring timing
let normalizedPanVelocity: // how to normalize pan velocity
runningAnimators.forEach { $0.continueAnimation(withTimingParameters: spring(for: velocity()), durationFactor: 0) }
}
}
func velocity() -> CGVector {
let pan = panRecognizer
let progress = runningAnimators[0].fractionComplete
let fraction = popupOffset*(1 - progress)
return CGVector(with: pan.velocity(in: view), fraction: fraction)
}
func spring(for velocity: CGVector = .zero) -> UITimingCurveProvider {
return UISpringTimingParameters(dampingRatio: 0.9, initialVelocity: velocity)//UISpringTimingParameters(mass: 2.5, stiffness: 80, damping: 25, initialVelocity: velocity)
}
the problem is when I quickly swipe up or down menu and release the finer, it seems animation hit the wall (slow quickly), then continue to rest
so how can I fix the issue? I have tried the whole day but I couldn't fix it
Upvotes: 4
Views: 1540
Reputation: 1137
The documentation for the UISpringTimingParameters
says:
https://developer.apple.com/documentation/uikit/uispringtimingparameters/1649832-init
A vector with a magnitude of 1.0 corresponds to an initial velocity that would cover the total animation distance in one second. For example, if the total animation distance is 200 points and the view’s initial velocity is 100 points per second, specify a vector with a magnitude of 0.5.
Meaning that you have to normalize the velocity using the with of the view.
And looking at the official documentation for CGVector
the initializer you are using is confusingly not documented.
https://developer.apple.com/documentation/coregraphics/cgvector
What I've ended up doing was, calculating the normalized vector by myself.
You would need to calculate the total points the view is moving from the start of the animation to the end and then using this distanceToMove
to make a "unit vector" from it / normalizing it:
let distanceToMove = newY - oldY
let velocity = recognizer.velocity(in: view)
let relativeVelocityY = velocity.x / distanceToMove
let relativeVelocity = CGVector(dx: 0, dy: relativeVelocityY)
let timing = UISpringTimingParameters(dampingRatio: 0.9, initialVelocity: relativeVelocity)
Let me know if this worked for you.
Upvotes: 4