@studiometa/js-toolkit
Version:
A set of useful little bits of JavaScript to boost your project! 🚀
97 lines (96 loc) • 2.69 kB
JavaScript
import { cubicBezier } from "@motionone/easing";
import { lerp, map, clamp01, damp, inertiaFinalValue } from "./math/index.js";
import { isDefined, isArray, isNumber } from "./is.js";
import { noop, noopValue as linear } from "./noop.js";
import { useRaf } from "../services/RafService.js";
let id = 0;
const DEFAULT_PROGRESS_PRECISION = 1e-4;
function normalizeEase(ease) {
if (!isDefined(ease)) {
return linear;
}
if (isArray(ease)) {
return cubicBezier(...ease);
}
return ease;
}
function tween(callback, options = {}) {
const raf = useRaf();
let progressValue = 0;
let easedProgress = 0;
const isSmooth = isDefined(options.smooth) && (isNumber(options.smooth) || options.smooth);
const smoothFactor = isNumber(options.smooth) ? options.smooth : 0.1;
const precision = options.precision ?? DEFAULT_PROGRESS_PRECISION;
const ease = normalizeEase(options.easing);
let delay = options.delay ?? 0;
delay *= 1e3;
let duration = options.duration ?? 1;
duration *= 1e3;
let startTime = getStartTime();
let endTime = getEndTime(startTime);
const key = `tw-${id}`;
id += 1;
const { onStart = noop, onProgress = noop, onFinish = noop } = options;
let isRunning = false;
function pause() {
isRunning = false;
raf.remove(key);
}
function progress(newProgress) {
if (!isDefined(newProgress)) {
return easedProgress;
}
progressValue = newProgress;
easedProgress = isSmooth ? damp(progressValue, easedProgress, smoothFactor, precision) : ease(progressValue);
if (Math.abs(1 - easedProgress) < precision) {
progressValue = 1;
easedProgress = 1;
}
callback(easedProgress);
onProgress(easedProgress);
if (easedProgress === 1) {
pause();
requestAnimationFrame(() => onFinish(easedProgress));
}
return easedProgress;
}
function tick(props) {
progress(clamp01(map(props.time, startTime, endTime, 0, 1)));
}
function getStartTime() {
return performance.now() + delay;
}
function getEndTime(time) {
return isSmooth ? inertiaFinalValue(time, 1) : time + duration;
}
function start() {
onStart(0);
startTime = getStartTime();
endTime = getEndTime(startTime);
progressValue = 0;
easedProgress = 0;
isRunning = true;
raf.add(key, tick);
}
function play() {
if (isRunning) {
return;
}
startTime = getStartTime() - lerp(0, duration, progressValue);
endTime = getEndTime(startTime);
isRunning = true;
raf.add(key, tick);
}
return {
start,
finish: () => progress(1),
pause,
play,
progress
};
}
export {
normalizeEase,
tween
};
//# sourceMappingURL=tween.js.map