This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
2021-04-02 02:24:13 +03:00

73 lines
3.7 KiB
JavaScript

import { cond, sub, divide, multiply, sqrt, add, block, set, exp, sin, cos, eq, or, neq, and, lessThan, greaterThan, proc, min, abs } from '../base';
import AnimatedValue from '../core/InternalAnimatedValue';
const MAX_STEPS_MS = 64;
function spring(clock, state, config) {
const lastTime = cond(state.time, state.time, clock);
const deltaTime = min(sub(clock, lastTime), MAX_STEPS_MS);
const c = config.damping;
const m = config.mass;
const k = config.stiffness;
const v0 = multiply(-1, state.velocity);
const x0 = sub(config.toValue, state.position);
const zeta = divide(c, multiply(2, sqrt(multiply(k, m)))); // damping ratio
const omega0 = sqrt(divide(k, m)); // undamped angular frequency of the oscillator (rad/ms)
const omega1 = multiply(omega0, sqrt(sub(1, multiply(zeta, zeta)))); // exponential decay
const t = divide(deltaTime, 1000); // in seconds
const sin1 = sin(multiply(omega1, t));
const cos1 = cos(multiply(omega1, t)); // under damped
const underDampedEnvelope = exp(multiply(-1, zeta, omega0, t));
const underDampedFrag1 = multiply(underDampedEnvelope, add(multiply(sin1, divide(add(v0, multiply(zeta, omega0, x0)), omega1)), multiply(x0, cos1)));
const underDampedPosition = sub(config.toValue, underDampedFrag1); // This looks crazy -- it's actually just the derivative of the oscillation function
const underDampedVelocity = sub(multiply(zeta, omega0, underDampedFrag1), multiply(underDampedEnvelope, sub(multiply(cos1, add(v0, multiply(zeta, omega0, x0))), multiply(omega1, x0, sin1)))); // critically damped
const criticallyDampedEnvelope = exp(multiply(-1, omega0, t));
const criticallyDampedPosition = sub(config.toValue, multiply(criticallyDampedEnvelope, add(x0, multiply(add(v0, multiply(omega0, x0)), t))));
const criticallyDampedVelocity = multiply(criticallyDampedEnvelope, add(multiply(v0, sub(multiply(t, omega0), 1)), multiply(t, x0, omega0, omega0))); // conditions for stopping the spring animations
const prevPosition = state.prevPosition ? state.prevPosition : new AnimatedValue(0);
const isOvershooting = cond(and(config.overshootClamping, neq(config.stiffness, 0)), cond(lessThan(prevPosition, config.toValue), greaterThan(state.position, config.toValue), lessThan(state.position, config.toValue)));
const isVelocity = lessThan(abs(state.velocity), config.restSpeedThreshold);
const isDisplacement = or(eq(config.stiffness, 0), lessThan(abs(sub(config.toValue, state.position)), config.restDisplacementThreshold));
return block([set(prevPosition, state.position), cond(lessThan(zeta, 1), [set(state.position, underDampedPosition), set(state.velocity, underDampedVelocity)], [set(state.position, criticallyDampedPosition), set(state.velocity, criticallyDampedVelocity)]), set(state.time, clock), cond(or(isOvershooting, and(isVelocity, isDisplacement)), [cond(neq(config.stiffness, 0), [set(state.velocity, 0), set(state.position, config.toValue)]), set(state.finished, 1)])]);
}
const procSpring = proc((finished, velocity, position, time, prevPosition, toValue, damping, mass, stiffness, overshootClamping, restSpeedThreshold, restDisplacementThreshold, clock) => spring(clock, {
finished,
velocity,
position,
time,
// @ts-ignore
prevPosition
}, {
toValue,
damping,
mass,
stiffness,
overshootClamping,
restDisplacementThreshold,
restSpeedThreshold
}));
export default ((clock, {
finished,
velocity,
position,
time,
// @ts-ignore
prevPosition
}, {
toValue,
damping,
mass,
stiffness,
overshootClamping,
restDisplacementThreshold,
restSpeedThreshold
}) => procSpring(finished, velocity, position, time, prevPosition, toValue, damping, mass, stiffness, overshootClamping, restSpeedThreshold, restDisplacementThreshold, clock));
//# sourceMappingURL=spring.js.map