Skip to content

Instantly share code, notes, and snippets.

@jakearchibald
Last active March 20, 2023 17:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakearchibald/9718d1b81fe62d1c9655de65df1a55a4 to your computer and use it in GitHub Desktop.
Save jakearchibald/9718d1b81fe62d1c9655de65df1a55a4 to your computer and use it in GitHub Desktop.
function spring({ mass, stiffness, damping, velocity }) {
const w0 = Math.sqrt(stiffness / mass);
const zeta = damping / (2 * Math.sqrt(stiffness * mass));
const wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0;
const b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0;
function solver(t) {
if (zeta < 1) {
t =
Math.exp(-t * zeta * w0) *
(1 * Math.cos(wd * t) + b * Math.sin(wd * t));
} else {
t = (1 + b * t) * Math.exp(-t * w0);
}
return 1 - t;
}
const duration = (() => {
const step = 1 / 6;
let time = 0;
while (true) {
if (Math.abs(1 - solver(time)) < 0.001) {
const restStart = time;
let restSteps = 1;
while (true) {
time += step;
if (Math.abs(1 - solver(time)) >= 0.001) break;
restSteps++;
if (restSteps === 16) return restStart;
}
}
time += step;
}
})();
return [duration * 1000, (t) => solver(duration * t)];
}
const [idealDuration, easingFunc] = spring({
mass: 1,
stiffness: 100,
damping: 10,
velocity: 0,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment