Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Spring Animator
//Changing values
var numberVelocity = CGFloat(0)
var runningTime = TimeInterval(0)
//Resting position of spring
let endNumberValue = CGFloat(300)
//Set relaxation time (duration in seconds)
let relaxationTime = 1
//Spring constants
let damping = 0.9
let stiffness = 5
let mass = (pow(relaxationTime, 2) * pow(damping, 2)) / (16 * stiffness)
internal func springFunction(_ currentValue: CGFloat, _ length: CGFloat, _ velocity: inout CGFloat) -> CGFloat {
let displacement = currentValue - length
let springForce = -stiffness * displacement // Hooke's Law (F = -kx) (where k is stiffness constant and x is displacement value)
let forceDamper = -damping * velocity // F = -dv (where d is damping constant and v is velocity)
let dampedForce = springForce + forceDamper
let acceleration = dampedForce / mass // a = F / m
let refreshRate: CGFloat = 1/60 //Hz
velocity += acceleration * refreshRate
let position = velocity * refreshRate
return position
}
public func animateProperty(_ property: inout CGFloat, _ runningTime: TimeInterval) {
if runningTime < relaxationTime {
property += springFunction(property, endNumberValue, &numberVelocity)
} else {
//Set final value to exact value
property = endNumberValue
}
}
//Put this inside a CADisplayLink updating the running time and your view origin will animate in a spring
animateProperty(myView.frame.origin.y, runningTime)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment