@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
46 lines (45 loc) • 2.05 kB
JavaScript
/**
* ESLIncrementalScrollAxisStepper encapsulates per-axis easing/acceleration logic.
* It receives raw distance to target (signed) and returns incremental delta to apply this frame.
*/
export class ESLIncrementalScrollAxisStepper {
constructor(calcDistance, options) {
this.calcDistance = calcDistance;
this.options = options;
this.lastUnstableTime = 0;
this.maxStepIncrement = 1;
this.initialTime = Date.now();
this.startTime = this.initialTime;
}
/**
* Computes the scroll delta for current animation frame.
* Returns 0 when target is reached (distance less than 1px).
* Gradually increases step size for smooth acceleration.
*/
computeStep(options) {
const distance = this.calcDistance(options);
const distanceAbs = Math.abs(distance);
if (distanceAbs <= 1) {
// stable, updating time, not escalating maxStepIncrement
this.startTime = Date.now();
return 0;
}
const now = Date.now();
// The speed of incremental scroll (px/ms) depends on the distance to the target position
const speed = Math.floor(distanceAbs / 100) + 1;
// The step increment limits by maxStepIncrement and provides a smooth start to scrolling
const stepIncrement = Math.min(this.maxStepIncrement, speed * (now - this.startTime));
this.startTime = now;
const increment = Math.floor(Math.min(distanceAbs, stepIncrement));
const direction = distance > 0 ? increment : -increment;
this.lastUnstableTime = this.startTime;
if (this.maxStepIncrement < 1000)
this.maxStepIncrement *= 2;
return direction;
}
/** Determines if scrolling should continue. Stops when stability threshold is exceeded or timeout is reached */
shouldContinueStepping() {
return this.startTime - this.lastUnstableTime < this.options.stabilityThreshold &&
this.startTime - this.initialTime < this.options.timeout;
}
}