mouse-wheel.esm.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /*!
  2. * better-scroll / mouse-wheel
  3. * (c) 2016-2021 ustbhuangyi
  4. * Released under the MIT License.
  5. */
  6. function warn(msg) {
  7. console.error("[BScroll warn]: " + msg);
  8. }
  9. // ssr support
  10. var inBrowser = typeof window !== 'undefined';
  11. var ua = inBrowser && navigator.userAgent.toLowerCase();
  12. !!(ua && /wechatdevtools/.test(ua));
  13. ua && ua.indexOf('android') > 0;
  14. /* istanbul ignore next */
  15. ((function () {
  16. if (typeof ua === 'string') {
  17. var regex = /os (\d\d?_\d(_\d)?)/;
  18. var matches = regex.exec(ua);
  19. if (!matches)
  20. return false;
  21. var parts = matches[1].split('_').map(function (item) {
  22. return parseInt(item, 10);
  23. });
  24. // ios version >= 13.4 issue 982
  25. return !!(parts[0] === 13 && parts[1] >= 4);
  26. }
  27. return false;
  28. }))();
  29. /* istanbul ignore next */
  30. var supportsPassive = false;
  31. /* istanbul ignore next */
  32. if (inBrowser) {
  33. var EventName = 'test-passive';
  34. try {
  35. var opts = {};
  36. Object.defineProperty(opts, 'passive', {
  37. get: function () {
  38. supportsPassive = true;
  39. },
  40. }); // https://github.com/facebook/flow/issues/285
  41. window.addEventListener(EventName, function () { }, opts);
  42. }
  43. catch (e) { }
  44. }
  45. var extend = function (target, source) {
  46. for (var key in source) {
  47. target[key] = source[key];
  48. }
  49. return target;
  50. };
  51. var elementStyle = (inBrowser &&
  52. document.createElement('div').style);
  53. var vendor = (function () {
  54. /* istanbul ignore if */
  55. if (!inBrowser) {
  56. return false;
  57. }
  58. var transformNames = [
  59. {
  60. key: 'standard',
  61. value: 'transform',
  62. },
  63. {
  64. key: 'webkit',
  65. value: 'webkitTransform',
  66. },
  67. {
  68. key: 'Moz',
  69. value: 'MozTransform',
  70. },
  71. {
  72. key: 'O',
  73. value: 'OTransform',
  74. },
  75. {
  76. key: 'ms',
  77. value: 'msTransform',
  78. },
  79. ];
  80. for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
  81. var obj = transformNames_1[_i];
  82. if (elementStyle[obj.value] !== undefined) {
  83. return obj.key;
  84. }
  85. }
  86. /* istanbul ignore next */
  87. return false;
  88. })();
  89. /* istanbul ignore next */
  90. function prefixStyle(style) {
  91. if (vendor === false) {
  92. return style;
  93. }
  94. if (vendor === 'standard') {
  95. if (style === 'transitionEnd') {
  96. return 'transitionend';
  97. }
  98. return style;
  99. }
  100. return vendor + style.charAt(0).toUpperCase() + style.substr(1);
  101. }
  102. function addEvent(el, type, fn, capture) {
  103. var useCapture = supportsPassive
  104. ? {
  105. passive: false,
  106. capture: !!capture,
  107. }
  108. : !!capture;
  109. el.addEventListener(type, fn, useCapture);
  110. }
  111. function removeEvent(el, type, fn, capture) {
  112. el.removeEventListener(type, fn, {
  113. capture: !!capture,
  114. });
  115. }
  116. vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
  117. var transform = prefixStyle('transform');
  118. var transition = prefixStyle('transition');
  119. inBrowser && prefixStyle('perspective') in elementStyle;
  120. ({
  121. transform: transform,
  122. transition: transition,
  123. transitionTimingFunction: prefixStyle('transitionTimingFunction'),
  124. transitionDuration: prefixStyle('transitionDuration'),
  125. transitionDelay: prefixStyle('transitionDelay'),
  126. transformOrigin: prefixStyle('transformOrigin'),
  127. transitionEnd: prefixStyle('transitionEnd'),
  128. transitionProperty: prefixStyle('transitionProperty'),
  129. });
  130. function preventDefaultExceptionFn(el, exceptions) {
  131. for (var i in exceptions) {
  132. if (exceptions[i].test(el[i])) {
  133. return true;
  134. }
  135. }
  136. return false;
  137. }
  138. var EventRegister = /** @class */ (function () {
  139. function EventRegister(wrapper, events) {
  140. this.wrapper = wrapper;
  141. this.events = events;
  142. this.addDOMEvents();
  143. }
  144. EventRegister.prototype.destroy = function () {
  145. this.removeDOMEvents();
  146. this.events = [];
  147. };
  148. EventRegister.prototype.addDOMEvents = function () {
  149. this.handleDOMEvents(addEvent);
  150. };
  151. EventRegister.prototype.removeDOMEvents = function () {
  152. this.handleDOMEvents(removeEvent);
  153. };
  154. EventRegister.prototype.handleDOMEvents = function (eventOperation) {
  155. var _this = this;
  156. var wrapper = this.wrapper;
  157. this.events.forEach(function (event) {
  158. eventOperation(wrapper, event.name, _this, !!event.capture);
  159. });
  160. };
  161. EventRegister.prototype.handleEvent = function (e) {
  162. var eventType = e.type;
  163. this.events.some(function (event) {
  164. if (event.name === eventType) {
  165. event.handler(e);
  166. return true;
  167. }
  168. return false;
  169. });
  170. };
  171. return EventRegister;
  172. }());
  173. var MouseWheel = /** @class */ (function () {
  174. function MouseWheel(scroll) {
  175. this.scroll = scroll;
  176. this.wheelEndTimer = 0;
  177. this.wheelMoveTimer = 0;
  178. this.wheelStart = false;
  179. this.init();
  180. }
  181. MouseWheel.prototype.init = function () {
  182. this.handleBScroll();
  183. this.handleOptions();
  184. this.handleHooks();
  185. this.registerEvent();
  186. };
  187. MouseWheel.prototype.handleBScroll = function () {
  188. this.scroll.registerType([
  189. 'alterOptions',
  190. 'mousewheelStart',
  191. 'mousewheelMove',
  192. 'mousewheelEnd',
  193. ]);
  194. };
  195. MouseWheel.prototype.handleOptions = function () {
  196. var userOptions = (this.scroll.options.mouseWheel === true
  197. ? {}
  198. : this.scroll.options.mouseWheel);
  199. var defaultOptions = {
  200. speed: 20,
  201. invert: false,
  202. easeTime: 300,
  203. discreteTime: 400,
  204. throttleTime: 0,
  205. dampingFactor: 0.1,
  206. };
  207. this.mouseWheelOpt = extend(defaultOptions, userOptions);
  208. };
  209. MouseWheel.prototype.handleHooks = function () {
  210. this.hooksFn = [];
  211. this.registerHooks(this.scroll.hooks, 'destroy', this.destroy);
  212. };
  213. MouseWheel.prototype.registerEvent = function () {
  214. this.eventRegister = new EventRegister(this.scroll.scroller.wrapper, [
  215. {
  216. name: 'wheel',
  217. handler: this.wheelHandler.bind(this),
  218. },
  219. {
  220. name: 'mousewheel',
  221. handler: this.wheelHandler.bind(this),
  222. },
  223. {
  224. name: 'DOMMouseScroll',
  225. handler: this.wheelHandler.bind(this),
  226. },
  227. ]);
  228. };
  229. MouseWheel.prototype.registerHooks = function (hooks, name, handler) {
  230. hooks.on(name, handler, this);
  231. this.hooksFn.push([hooks, name, handler]);
  232. };
  233. MouseWheel.prototype.wheelHandler = function (e) {
  234. if (!this.scroll.enabled) {
  235. return;
  236. }
  237. this.beforeHandler(e);
  238. // start
  239. if (!this.wheelStart) {
  240. this.wheelStartHandler(e);
  241. this.wheelStart = true;
  242. }
  243. // move
  244. var delta = this.getWheelDelta(e);
  245. this.wheelMoveHandler(delta);
  246. // end
  247. this.wheelEndDetector(delta);
  248. };
  249. MouseWheel.prototype.wheelStartHandler = function (e) {
  250. this.cleanCache();
  251. var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
  252. scrollBehaviorX.setMovingDirection(0 /* Default */);
  253. scrollBehaviorY.setMovingDirection(0 /* Default */);
  254. scrollBehaviorX.setDirection(0 /* Default */);
  255. scrollBehaviorY.setDirection(0 /* Default */);
  256. this.scroll.trigger(this.scroll.eventTypes.alterOptions, this.mouseWheelOpt);
  257. this.scroll.trigger(this.scroll.eventTypes.mousewheelStart);
  258. };
  259. MouseWheel.prototype.cleanCache = function () {
  260. this.deltaCache = [];
  261. };
  262. MouseWheel.prototype.wheelMoveHandler = function (delta) {
  263. var _this = this;
  264. var _a = this.mouseWheelOpt, throttleTime = _a.throttleTime, dampingFactor = _a.dampingFactor;
  265. if (throttleTime && this.wheelMoveTimer) {
  266. this.deltaCache.push(delta);
  267. }
  268. else {
  269. var cachedDelta = this.deltaCache.reduce(function (prev, current) {
  270. return {
  271. x: prev.x + current.x,
  272. y: prev.y + current.y,
  273. };
  274. }, { x: 0, y: 0 });
  275. this.cleanCache();
  276. var _b = this.scroll.scroller, scrollBehaviorX = _b.scrollBehaviorX, scrollBehaviorY = _b.scrollBehaviorY;
  277. scrollBehaviorX.setMovingDirection(-delta.directionX);
  278. scrollBehaviorY.setMovingDirection(-delta.directionY);
  279. scrollBehaviorX.setDirection(delta.x);
  280. scrollBehaviorY.setDirection(delta.y);
  281. // when out of boundary, perform a damping scroll
  282. var newX = scrollBehaviorX.performDampingAlgorithm(Math.round(delta.x) + cachedDelta.x, dampingFactor);
  283. var newY = scrollBehaviorY.performDampingAlgorithm(Math.round(delta.y) + cachedDelta.x, dampingFactor);
  284. if (!this.scroll.trigger(this.scroll.eventTypes.mousewheelMove, {
  285. x: newX,
  286. y: newY,
  287. })) {
  288. var easeTime = this.getEaseTime();
  289. if (newX !== this.scroll.x || newY !== this.scroll.y) {
  290. this.scroll.scrollTo(newX, newY, easeTime);
  291. }
  292. }
  293. if (throttleTime) {
  294. this.wheelMoveTimer = window.setTimeout(function () {
  295. _this.wheelMoveTimer = 0;
  296. }, throttleTime);
  297. }
  298. }
  299. };
  300. MouseWheel.prototype.wheelEndDetector = function (delta) {
  301. var _this = this;
  302. window.clearTimeout(this.wheelEndTimer);
  303. this.wheelEndTimer = window.setTimeout(function () {
  304. _this.wheelStart = false;
  305. window.clearTimeout(_this.wheelMoveTimer);
  306. _this.wheelMoveTimer = 0;
  307. _this.scroll.trigger(_this.scroll.eventTypes.mousewheelEnd, delta);
  308. }, this.mouseWheelOpt.discreteTime);
  309. };
  310. MouseWheel.prototype.getWheelDelta = function (e) {
  311. var _a = this.mouseWheelOpt, speed = _a.speed, invert = _a.invert;
  312. var wheelDeltaX = 0;
  313. var wheelDeltaY = 0;
  314. var direction = invert ? -1 /* Negative */ : 1 /* Positive */;
  315. switch (true) {
  316. case 'deltaX' in e:
  317. if (e.deltaMode === 1) {
  318. wheelDeltaX = -e.deltaX * speed;
  319. wheelDeltaY = -e.deltaY * speed;
  320. }
  321. else {
  322. wheelDeltaX = -e.deltaX;
  323. wheelDeltaY = -e.deltaY;
  324. }
  325. break;
  326. case 'wheelDeltaX' in e:
  327. wheelDeltaX = (e.wheelDeltaX / 120) * speed;
  328. wheelDeltaY = (e.wheelDeltaY / 120) * speed;
  329. break;
  330. case 'wheelDelta' in e:
  331. wheelDeltaX = wheelDeltaY = (e.wheelDelta / 120) * speed;
  332. break;
  333. case 'detail' in e:
  334. wheelDeltaX = wheelDeltaY = (-e.detail / 3) * speed;
  335. break;
  336. }
  337. wheelDeltaX *= direction;
  338. wheelDeltaY *= direction;
  339. if (!this.scroll.hasVerticalScroll) {
  340. if (Math.abs(wheelDeltaY) > Math.abs(wheelDeltaX)) {
  341. wheelDeltaX = wheelDeltaY;
  342. }
  343. wheelDeltaY = 0;
  344. }
  345. if (!this.scroll.hasHorizontalScroll) {
  346. wheelDeltaX = 0;
  347. }
  348. var directionX = wheelDeltaX > 0
  349. ? -1 /* Negative */
  350. : wheelDeltaX < 0
  351. ? 1 /* Positive */
  352. : 0 /* Default */;
  353. var directionY = wheelDeltaY > 0
  354. ? -1 /* Negative */
  355. : wheelDeltaY < 0
  356. ? 1 /* Positive */
  357. : 0 /* Default */;
  358. return {
  359. x: wheelDeltaX,
  360. y: wheelDeltaY,
  361. directionX: directionX,
  362. directionY: directionY,
  363. };
  364. };
  365. MouseWheel.prototype.beforeHandler = function (e) {
  366. var _a = this.scroll.options, preventDefault = _a.preventDefault, stopPropagation = _a.stopPropagation, preventDefaultException = _a.preventDefaultException;
  367. if (preventDefault &&
  368. !preventDefaultExceptionFn(e.target, preventDefaultException)) {
  369. e.preventDefault();
  370. }
  371. if (stopPropagation) {
  372. e.stopPropagation();
  373. }
  374. };
  375. MouseWheel.prototype.getEaseTime = function () {
  376. var SAFE_EASETIME = 100;
  377. var easeTime = this.mouseWheelOpt.easeTime;
  378. // scrollEnd event will be triggered in every calling of scrollTo when easeTime is too small
  379. // easeTime needs to be greater than 100
  380. if (easeTime < SAFE_EASETIME) {
  381. warn("easeTime should be greater than 100." +
  382. "If mouseWheel easeTime is too small," +
  383. "scrollEnd will be triggered many times.");
  384. }
  385. return Math.max(easeTime, SAFE_EASETIME);
  386. };
  387. MouseWheel.prototype.destroy = function () {
  388. this.eventRegister.destroy();
  389. window.clearTimeout(this.wheelEndTimer);
  390. window.clearTimeout(this.wheelMoveTimer);
  391. this.hooksFn.forEach(function (item) {
  392. var hooks = item[0];
  393. var hooksName = item[1];
  394. var handlerFn = item[2];
  395. hooks.off(hooksName, handlerFn);
  396. });
  397. };
  398. MouseWheel.pluginName = 'mouseWheel';
  399. MouseWheel.applyOrder = "pre" /* Pre */;
  400. return MouseWheel;
  401. }());
  402. export default MouseWheel;