Episode #232

Calculating Spring Velocity

8 minutes
Published on August 19, 2016

This video is only available to subscribers. Get access to this video and 572 others.

UIView has an incredibly useful spring-based animation API, but it can be difficult to know what to use for the damping and initial spring velocity parameters. In this episode, we'll break down how to compute the velocity value using the values we get from our UIPanGestureRecognizer and a little math.

Episode Links

Handling the End Gesture State

In the gesture recognizer method, we handle the .Ended state by computing the following:

  • the target point we are going to animate to
  • the view's current velocity in its parent, given to us by UIPanGestureRecognizer
  • the overall distance we need to travel
  • the relative distance our velocity vector makes up

Using these values, we can calculate our spring animations initial velocity:

 case .Ended:
            let velocity = recognizer.velocityInView(parent)
            print(velocity)

            let targetPoint = computeTargetPoint(view, location: centerInParent, velocity: velocity, bounds: parent.bounds)

            func magnitude(vector: CGPoint) -> CGFloat {
                return sqrt(pow(vector.x, 2) + pow(vector.y, 2))
            }

            let distanceVector = CGPoint(x: centerInParent.x - targetPoint.x, y: centerInParent.y - targetPoint.y)
            let totalDistance = magnitude(distanceVector)
            let magVelocity = magnitude(velocity)

            let animationDuration: NSTimeInterval = 1
            let springVelocity: CGFloat = magVelocity / totalDistance / CGFloat(animationDuration)


            UIView.animateWithDuration(animationDuration,
                                       delay: 0,
                                       usingSpringWithDamping: 0.9,
                                       initialSpringVelocity: springVelocity,
                                       options: [],
                                       animations: {
                recognizer.view!.center = targetPoint
            }, completion: nil)

This episode uses Xcode 7.3, Swift 2.3.