The physics behind spring animations - Maxime Heckel's Blog


/// <https://blog.maximeheckel.com/posts/the-physics-behind-spring-animations/>
struct SpringCalculator {

  private var velocity: Double

  init(
    velocity: Double = 0
  ) {
    self.velocity = velocity
  }

  mutating func calculate(
    additionalVelocity: Double = 0,
    position x: Double,
    time: TimeInterval = 0.2,
    gravity: CGFloat = 9.8,
    stiffness: CGFloat = 500,
    mass: CGFloat = 20,
    damping: CGFloat = 20
  ) -> CGFloat {

    velocity += additionalVelocity
    
    /* Spring stiffness, in kg / s^2 */
    let k: CGFloat = stiffness

    let fg = mass * gravity
    let fa = -k * x

    /* Damping constant, in kg / s */
    let fd = -damping * velocity

    // Accelleration
    let a = (fa + fd + fg) / mass

    let vy = velocity + a * time
    velocity = vy

    // New position
    let newValue = x + vy * time

    return newValue
  }

}