122 lines
4.6 KiB
JavaScript
122 lines
4.6 KiB
JavaScript
|
import { EventGroup } from './EventGroup';
|
||
|
import { findScrollableParent } from './scroll';
|
||
|
import { getRect } from './dom/getRect';
|
||
|
import { getWindow } from './dom';
|
||
|
var SCROLL_ITERATION_DELAY = 16;
|
||
|
var SCROLL_GUTTER = 100;
|
||
|
var MAX_SCROLL_VELOCITY = 15;
|
||
|
/**
|
||
|
* AutoScroll simply hooks up mouse events given a parent element, and scrolls the container
|
||
|
* up/down depending on how close the mouse is to the top/bottom of the container.
|
||
|
*
|
||
|
* Once you don't want autoscroll any more, just dispose the helper and it will unhook events.
|
||
|
*
|
||
|
* @public
|
||
|
* {@docCategory AutoScroll}
|
||
|
*/
|
||
|
var AutoScroll = /** @class */ (function () {
|
||
|
function AutoScroll(element, win) {
|
||
|
var theWin = win !== null && win !== void 0 ? win : getWindow(element);
|
||
|
this._events = new EventGroup(this);
|
||
|
this._scrollableParent = findScrollableParent(element);
|
||
|
this._incrementScroll = this._incrementScroll.bind(this);
|
||
|
this._scrollRect = getRect(this._scrollableParent, theWin);
|
||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
if (this._scrollableParent === theWin) {
|
||
|
this._scrollableParent = theWin.document.body;
|
||
|
}
|
||
|
if (this._scrollableParent) {
|
||
|
this._events.on(theWin, 'mousemove', this._onMouseMove, true);
|
||
|
this._events.on(theWin, 'touchmove', this._onTouchMove, true);
|
||
|
}
|
||
|
}
|
||
|
AutoScroll.prototype.dispose = function () {
|
||
|
this._events.dispose();
|
||
|
this._stopScroll();
|
||
|
};
|
||
|
AutoScroll.prototype._onMouseMove = function (ev) {
|
||
|
this._computeScrollVelocity(ev);
|
||
|
};
|
||
|
AutoScroll.prototype._onTouchMove = function (ev) {
|
||
|
if (ev.touches.length > 0) {
|
||
|
this._computeScrollVelocity(ev);
|
||
|
}
|
||
|
};
|
||
|
AutoScroll.prototype._computeScrollVelocity = function (ev) {
|
||
|
if (!this._scrollRect) {
|
||
|
return;
|
||
|
}
|
||
|
var clientX;
|
||
|
var clientY;
|
||
|
if ('clientX' in ev) {
|
||
|
clientX = ev.clientX;
|
||
|
clientY = ev.clientY;
|
||
|
}
|
||
|
else {
|
||
|
clientX = ev.touches[0].clientX;
|
||
|
clientY = ev.touches[0].clientY;
|
||
|
}
|
||
|
var scrollRectTop = this._scrollRect.top;
|
||
|
var scrollRectLeft = this._scrollRect.left;
|
||
|
var scrollClientBottom = scrollRectTop + this._scrollRect.height - SCROLL_GUTTER;
|
||
|
var scrollClientRight = scrollRectLeft + this._scrollRect.width - SCROLL_GUTTER;
|
||
|
// variables to use for alternating scroll direction
|
||
|
var scrollRect;
|
||
|
var clientDirection;
|
||
|
var scrollClient;
|
||
|
// if either of these conditions are met we are scrolling vertically else horizontally
|
||
|
if (clientY < scrollRectTop + SCROLL_GUTTER || clientY > scrollClientBottom) {
|
||
|
clientDirection = clientY;
|
||
|
scrollRect = scrollRectTop;
|
||
|
scrollClient = scrollClientBottom;
|
||
|
this._isVerticalScroll = true;
|
||
|
}
|
||
|
else {
|
||
|
clientDirection = clientX;
|
||
|
scrollRect = scrollRectLeft;
|
||
|
scrollClient = scrollClientRight;
|
||
|
this._isVerticalScroll = false;
|
||
|
}
|
||
|
// calculate scroll velocity and direction
|
||
|
if (clientDirection < scrollRect + SCROLL_GUTTER) {
|
||
|
this._scrollVelocity = Math.max(-MAX_SCROLL_VELOCITY, -MAX_SCROLL_VELOCITY * ((SCROLL_GUTTER - (clientDirection - scrollRect)) / SCROLL_GUTTER));
|
||
|
}
|
||
|
else if (clientDirection > scrollClient) {
|
||
|
this._scrollVelocity = Math.min(MAX_SCROLL_VELOCITY, MAX_SCROLL_VELOCITY * ((clientDirection - scrollClient) / SCROLL_GUTTER));
|
||
|
}
|
||
|
else {
|
||
|
this._scrollVelocity = 0;
|
||
|
}
|
||
|
if (this._scrollVelocity) {
|
||
|
this._startScroll();
|
||
|
}
|
||
|
else {
|
||
|
this._stopScroll();
|
||
|
}
|
||
|
};
|
||
|
AutoScroll.prototype._startScroll = function () {
|
||
|
if (!this._timeoutId) {
|
||
|
this._incrementScroll();
|
||
|
}
|
||
|
};
|
||
|
AutoScroll.prototype._incrementScroll = function () {
|
||
|
if (this._scrollableParent) {
|
||
|
if (this._isVerticalScroll) {
|
||
|
this._scrollableParent.scrollTop += Math.round(this._scrollVelocity);
|
||
|
}
|
||
|
else {
|
||
|
this._scrollableParent.scrollLeft += Math.round(this._scrollVelocity);
|
||
|
}
|
||
|
}
|
||
|
this._timeoutId = setTimeout(this._incrementScroll, SCROLL_ITERATION_DELAY);
|
||
|
};
|
||
|
AutoScroll.prototype._stopScroll = function () {
|
||
|
if (this._timeoutId) {
|
||
|
clearTimeout(this._timeoutId);
|
||
|
delete this._timeoutId;
|
||
|
}
|
||
|
};
|
||
|
return AutoScroll;
|
||
|
}());
|
||
|
export { AutoScroll };
|
||
|
//# sourceMappingURL=AutoScroll.js.map
|