66 lines
2.5 KiB
JavaScript
66 lines
2.5 KiB
JavaScript
import { animate } from './index.mjs';
|
|
import { velocityPerSecond } from '../utils/velocity-per-second.mjs';
|
|
import { getFrameData } from 'framesync';
|
|
|
|
function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
let currentAnimation;
|
|
function isOutOfBounds(v) {
|
|
return (min !== undefined && v < min) || (max !== undefined && v > max);
|
|
}
|
|
function boundaryNearest(v) {
|
|
if (min === undefined)
|
|
return max;
|
|
if (max === undefined)
|
|
return min;
|
|
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
|
|
}
|
|
function startAnimation(options) {
|
|
currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop();
|
|
currentAnimation = animate(Object.assign(Object.assign({}, options), { driver, onUpdate: (v) => {
|
|
var _a;
|
|
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(v);
|
|
(_a = options.onUpdate) === null || _a === void 0 ? void 0 : _a.call(options, v);
|
|
}, onComplete,
|
|
onStop }));
|
|
}
|
|
function startSpring(options) {
|
|
startAnimation(Object.assign({ type: "spring", stiffness: bounceStiffness, damping: bounceDamping, restDelta }, options));
|
|
}
|
|
if (isOutOfBounds(from)) {
|
|
startSpring({ from, velocity, to: boundaryNearest(from) });
|
|
}
|
|
else {
|
|
let target = power * velocity + from;
|
|
if (typeof modifyTarget !== "undefined")
|
|
target = modifyTarget(target);
|
|
const boundary = boundaryNearest(target);
|
|
const heading = boundary === min ? -1 : 1;
|
|
let prev;
|
|
let current;
|
|
const checkBoundary = (v) => {
|
|
prev = current;
|
|
current = v;
|
|
velocity = velocityPerSecond(v - prev, getFrameData().delta);
|
|
if ((heading === 1 && v > boundary) ||
|
|
(heading === -1 && v < boundary)) {
|
|
startSpring({ from: v, to: boundary, velocity });
|
|
}
|
|
};
|
|
startAnimation({
|
|
type: "decay",
|
|
from,
|
|
velocity,
|
|
timeConstant,
|
|
power,
|
|
restDelta,
|
|
modifyTarget,
|
|
onUpdate: isOutOfBounds(target) ? checkBoundary : undefined,
|
|
});
|
|
}
|
|
return {
|
|
stop: () => currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop(),
|
|
};
|
|
}
|
|
|
|
export { inertia };
|