|
|
|
|
@ -19,18 +19,17 @@ function tick_spring(ctx, last_value, current_value, target_value) {
|
|
|
|
|
const d = (velocity + acceleration) * ctx.dt;
|
|
|
|
|
if (Math.abs(d) < ctx.opts.precision && Math.abs(delta) < ctx.opts.precision) {
|
|
|
|
|
return target_value; // settled
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
ctx.settled = false; // signal loop to keep ticking
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
return is_date(current_value) ? new Date(current_value.getTime() + d) : current_value + d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (Array.isArray(current_value)) {
|
|
|
|
|
} else if (Array.isArray(current_value)) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
return current_value.map((_, i) => tick_spring(ctx, last_value[i], current_value[i], target_value[i]));
|
|
|
|
|
}
|
|
|
|
|
else if (typeof current_value === 'object') {
|
|
|
|
|
return current_value.map((_, i) =>
|
|
|
|
|
tick_spring(ctx, last_value[i], current_value[i], target_value[i])
|
|
|
|
|
);
|
|
|
|
|
} else if (typeof current_value === 'object') {
|
|
|
|
|
const next_value = {};
|
|
|
|
|
for (const k in current_value) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
@ -38,8 +37,7 @@ function tick_spring(ctx, last_value, current_value, target_value) {
|
|
|
|
|
}
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
return next_value;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(`Cannot spring ${typeof current_value} values`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -76,8 +74,7 @@ export function spring(value, opts = {}) {
|
|
|
|
|
last_value = new_value;
|
|
|
|
|
store.set((value = target_value));
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
}
|
|
|
|
|
else if (opts.soft) {
|
|
|
|
|
} else if (opts.soft) {
|
|
|
|
|
const rate = opts.soft === true ? 0.5 : +opts.soft;
|
|
|
|
|
inv_mass_recovery_rate = 1 / (rate * 60);
|
|
|
|
|
inv_mass = 0; // infinite mass, unaffected by spring forces
|
|
|
|
|
@ -110,8 +107,7 @@ export function spring(value, opts = {}) {
|
|
|
|
|
}
|
|
|
|
|
return new Promise((fulfil) => {
|
|
|
|
|
task.promise.then(() => {
|
|
|
|
|
if (token === current_token)
|
|
|
|
|
fulfil();
|
|
|
|
|
if (token === current_token) fulfil();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
@ -127,7 +123,6 @@ export function spring(value, opts = {}) {
|
|
|
|
|
return spring;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @typedef {(target_value: T, value: T) => T} Updater
|
|
|
|
|
* @template T
|
|
|
|
|
|