You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
13 KiB

/*!
* better-scroll / mouse-wheel
* (c) 2016-2020 ustbhuangyi
* Released under the MIT License.
*/
function warn(msg) {
console.error("[BScroll warn]: " + msg);
}
// ssr support
var inBrowser = typeof window !== 'undefined';
var ua = inBrowser && navigator.userAgent.toLowerCase();
var isWeChatDevTools = !!(ua && /wechatdevtools/.test(ua));
var isAndroid = ua && ua.indexOf('android') > 0;
/* istanbul ignore next */
var isIOSBadVersion = (function () {
if (typeof ua === 'string') {
var regex = /os (\d\d?_\d(_\d)?)/;
var matches = regex.exec(ua);
if (!matches)
return false;
var parts = matches[1].split('_').map(function (item) {
return parseInt(item, 10);
});
// ios version >= 13.4 issue 982
return !!(parts[0] >= 13 && parts[1] >= 4);
}
return false;
})();
var extend = function (target, source) {
for (var key in source) {
target[key] = source[key];
}
return target;
};
var elementStyle = (inBrowser &&
document.createElement('div').style);
var vendor = (function () {
/* istanbul ignore if */
if (!inBrowser) {
return false;
}
var transformNames = [
{
key: 'standard',
value: 'transform',
},
{
key: 'webkit',
value: 'webkitTransform',
},
{
key: 'Moz',
value: 'MozTransform',
},
{
key: 'O',
value: 'OTransform',
},
{
key: 'ms',
value: 'msTransform',
},
];
for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
var obj = transformNames_1[_i];
if (elementStyle[obj.value] !== undefined) {
return obj.key;
}
}
/* istanbul ignore next */
return false;
})();
/* istanbul ignore next */
function prefixStyle(style) {
if (vendor === false) {
return style;
}
if (vendor === 'standard') {
if (style === 'transitionEnd') {
return 'transitionend';
}
return style;
}
return vendor + style.charAt(0).toUpperCase() + style.substr(1);
}
function addEvent(el, type, fn, capture) {
el.addEventListener(type, fn, {
passive: false,
capture: !!capture,
});
}
function removeEvent(el, type, fn, capture) {
el.removeEventListener(type, fn, {
capture: !!capture,
});
}
var cssVendor = vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
var transform = prefixStyle('transform');
var transition = prefixStyle('transition');
var hasPerspective = inBrowser && prefixStyle('perspective') in elementStyle;
var style = {
transform: transform,
transition: transition,
transitionTimingFunction: prefixStyle('transitionTimingFunction'),
transitionDuration: prefixStyle('transitionDuration'),
transitionDelay: prefixStyle('transitionDelay'),
transformOrigin: prefixStyle('transformOrigin'),
transitionEnd: prefixStyle('transitionEnd'),
transitionProperty: prefixStyle('transitionProperty'),
};
function preventDefaultExceptionFn(el, exceptions) {
for (var i in exceptions) {
if (exceptions[i].test(el[i])) {
return true;
}
}
return false;
}
var EventRegister = /** @class */ (function () {
function EventRegister(wrapper, events) {
this.wrapper = wrapper;
this.events = events;
this.addDOMEvents();
}
EventRegister.prototype.destroy = function () {
this.removeDOMEvents();
this.events = [];
};
EventRegister.prototype.addDOMEvents = function () {
this.handleDOMEvents(addEvent);
};
EventRegister.prototype.removeDOMEvents = function () {
this.handleDOMEvents(removeEvent);
};
EventRegister.prototype.handleDOMEvents = function (eventOperation) {
var _this = this;
var wrapper = this.wrapper;
this.events.forEach(function (event) {
eventOperation(wrapper, event.name, _this, !!event.capture);
});
};
EventRegister.prototype.handleEvent = function (e) {
var eventType = e.type;
this.events.some(function (event) {
if (event.name === eventType) {
event.handler(e);
return true;
}
return false;
});
};
return EventRegister;
}());
var MouseWheel = /** @class */ (function () {
function MouseWheel(scroll) {
this.scroll = scroll;
this.wheelEndTimer = 0;
this.wheelMoveTimer = 0;
this.wheelStart = false;
this.init();
}
MouseWheel.prototype.init = function () {
this.handleBScroll();
this.handleOptions();
this.handleHooks();
this.registerEvent();
};
MouseWheel.prototype.handleBScroll = function () {
this.scroll.registerType([
'alterOptions',
'mousewheelStart',
'mousewheelMove',
'mousewheelEnd',
]);
};
MouseWheel.prototype.handleOptions = function () {
var userOptions = (this.scroll.options.mouseWheel === true
? {}
: this.scroll.options.mouseWheel);
var defaultOptions = {
speed: 20,
invert: false,
easeTime: 300,
discreteTime: 400,
throttleTime: 0,
dampingFactor: 0.1,
};
this.mouseWheelOpt = extend(defaultOptions, userOptions);
};
MouseWheel.prototype.handleHooks = function () {
this.hooksFn = [];
this.registerHooks(this.scroll.hooks, 'destroy', this.destroy);
};
MouseWheel.prototype.registerEvent = function () {
this.eventRegister = new EventRegister(this.scroll.scroller.wrapper, [
{
name: 'wheel',
handler: this.wheelHandler.bind(this),
},
{
name: 'mousewheel',
handler: this.wheelHandler.bind(this),
},
{
name: 'DOMMouseScroll',
handler: this.wheelHandler.bind(this),
},
]);
};
MouseWheel.prototype.registerHooks = function (hooks, name, handler) {
hooks.on(name, handler, this);
this.hooksFn.push([hooks, name, handler]);
};
MouseWheel.prototype.wheelHandler = function (e) {
if (!this.scroll.enabled) {
return;
}
this.beforeHandler(e);
// start
if (!this.wheelStart) {
this.wheelStartHandler(e);
this.wheelStart = true;
}
// move
var delta = this.getWheelDelta(e);
this.wheelMoveHandler(delta);
// end
this.wheelEndDetector(delta);
};
MouseWheel.prototype.wheelStartHandler = function (e) {
this.cleanCache();
var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
scrollBehaviorX.setMovingDirection(0 /* Default */);
scrollBehaviorY.setMovingDirection(0 /* Default */);
scrollBehaviorX.setDirection(0 /* Default */);
scrollBehaviorY.setDirection(0 /* Default */);
this.scroll.trigger(this.scroll.eventTypes.alterOptions, this.mouseWheelOpt);
this.scroll.trigger(this.scroll.eventTypes.mousewheelStart);
};
MouseWheel.prototype.cleanCache = function () {
this.deltaCache = [];
};
MouseWheel.prototype.wheelMoveHandler = function (delta) {
var _this = this;
var _a = this.mouseWheelOpt, throttleTime = _a.throttleTime, dampingFactor = _a.dampingFactor;
if (throttleTime && this.wheelMoveTimer) {
this.deltaCache.push(delta);
}
else {
var cachedDelta = this.deltaCache.reduce(function (prev, current) {
return {
x: prev.x + current.x,
y: prev.y + current.y,
};
}, { x: 0, y: 0 });
this.cleanCache();
var _b = this.scroll.scroller, scrollBehaviorX = _b.scrollBehaviorX, scrollBehaviorY = _b.scrollBehaviorY;
scrollBehaviorX.setMovingDirection(-delta.directionX);
scrollBehaviorY.setMovingDirection(-delta.directionY);
scrollBehaviorX.setDirection(delta.x);
scrollBehaviorY.setDirection(delta.y);
// when out of boundary, perform a damping scroll
var newX = scrollBehaviorX.performDampingAlgorithm(Math.round(delta.x) + cachedDelta.x, dampingFactor);
var newY = scrollBehaviorY.performDampingAlgorithm(Math.round(delta.y) + cachedDelta.x, dampingFactor);
if (!this.scroll.trigger(this.scroll.eventTypes.mousewheelMove, {
x: newX,
y: newY,
})) {
var easeTime = this.getEaseTime();
if (newX !== this.scroll.x || newY !== this.scroll.y) {
this.scroll.scrollTo(newX, newY, easeTime);
}
}
if (throttleTime) {
this.wheelMoveTimer = window.setTimeout(function () {
_this.wheelMoveTimer = 0;
}, throttleTime);
}
}
};
MouseWheel.prototype.wheelEndDetector = function (delta) {
var _this = this;
window.clearTimeout(this.wheelEndTimer);
this.wheelEndTimer = window.setTimeout(function () {
_this.wheelStart = false;
window.clearTimeout(_this.wheelMoveTimer);
_this.wheelMoveTimer = 0;
_this.scroll.trigger(_this.scroll.eventTypes.mousewheelEnd, delta);
}, this.mouseWheelOpt.discreteTime);
};
MouseWheel.prototype.getWheelDelta = function (e) {
var _a = this.mouseWheelOpt, speed = _a.speed, invert = _a.invert;
var wheelDeltaX = 0;
var wheelDeltaY = 0;
var direction = invert ? -1 /* Negative */ : 1 /* Positive */;
switch (true) {
case 'deltaX' in e:
if (e.deltaMode === 1) {
wheelDeltaX = -e.deltaX * speed;
wheelDeltaY = -e.deltaY * speed;
}
else {
wheelDeltaX = -e.deltaX;
wheelDeltaY = -e.deltaY;
}
break;
case 'wheelDeltaX' in e:
wheelDeltaX = (e.wheelDeltaX / 120) * speed;
wheelDeltaY = (e.wheelDeltaY / 120) * speed;
break;
case 'wheelDelta' in e:
wheelDeltaX = wheelDeltaY = (e.wheelDelta / 120) * speed;
break;
case 'detail' in e:
wheelDeltaX = wheelDeltaY = (-e.detail / 3) * speed;
break;
}
wheelDeltaX *= direction;
wheelDeltaY *= direction;
if (!this.scroll.hasVerticalScroll) {
wheelDeltaX = wheelDeltaY;
wheelDeltaY = 0;
}
if (!this.scroll.hasHorizontalScroll) {
wheelDeltaX = 0;
}
var directionX = wheelDeltaX > 0
? -1 /* Negative */
: wheelDeltaX < 0
? 1 /* Positive */
: 0 /* Default */;
var directionY = wheelDeltaY > 0
? -1 /* Negative */
: wheelDeltaY < 0
? 1 /* Positive */
: 0 /* Default */;
return {
x: wheelDeltaX,
y: wheelDeltaY,
directionX: directionX,
directionY: directionY,
};
};
MouseWheel.prototype.beforeHandler = function (e) {
var _a = this.scroll.options, preventDefault = _a.preventDefault, stopPropagation = _a.stopPropagation, preventDefaultException = _a.preventDefaultException;
if (preventDefault &&
!preventDefaultExceptionFn(e.target, preventDefaultException)) {
e.preventDefault();
}
if (stopPropagation) {
e.stopPropagation();
}
};
MouseWheel.prototype.getEaseTime = function () {
var SAFE_EASETIME = 100;
var easeTime = this.mouseWheelOpt.easeTime;
// scrollEnd event will be triggered in every calling of scrollTo when easeTime is too small
// easeTime needs to be greater than 100
if (easeTime < SAFE_EASETIME) {
warn("easeTime should be greater than 100." +
"If mouseWheel easeTime is too small," +
"scrollEnd will be triggered many times.");
}
return Math.max(easeTime, SAFE_EASETIME);
};
MouseWheel.prototype.destroy = function () {
this.eventRegister.destroy();
window.clearTimeout(this.wheelEndTimer);
window.clearTimeout(this.wheelMoveTimer);
this.hooksFn.forEach(function (item) {
var hooks = item[0];
var hooksName = item[1];
var handlerFn = item[2];
hooks.off(hooksName, handlerFn);
});
};
MouseWheel.pluginName = 'mouseWheel';
MouseWheel.applyOrder = "pre" /* Pre */;
return MouseWheel;
}());
export default MouseWheel;