Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Spring Animator
//: Playground - noun: a place where people can play
import UIKit
//Changing values
var initialVelocity = CGFloat(0)
var runningTime = CGFloat(0)
var myProperty = CGFloat(0)
//Resting position of spring
let endNumberValue = CGFloat(300)
//Set relaxation time (duration in seconds)
let relaxationTime = CGFloat(1)
//Spring constants
let dampingRatio = CGFloat(0.9)
let stiffness = CGFloat(15)
let mass = 0.0186975 * pow(dampingRatio, 2) * stiffness * pow(relaxationTime, 2)
let damping = 2 * mass * sqrt(stiffness/mass) * dampingRatio
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: CGFloat) {
if runningTime < relaxationTime {
property += springFunction(property, endNumberValue, &initialVelocity)
} else {
//Set final value to exact value
property = endNumberValue
}
}
while runningTime <= relaxationTime {
//Put this inside a CADisplayLink updating the running time and your view origin will animate in a spring
animateProperty(&myProperty, runningTime)
runningTime += 1/60
print(myProperty)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment