1 |
|
2 | import { getWindow } from 'ssr-window';
|
3 | import $ from '../../shared/dom.js';
|
4 | import { now, nextTick } from '../../shared/utils.js';
|
5 | export default function Mousewheel(_ref) {
|
6 | let {
|
7 | swiper,
|
8 | extendParams,
|
9 | on,
|
10 | emit
|
11 | } = _ref;
|
12 | const window = getWindow();
|
13 | extendParams({
|
14 | mousewheel: {
|
15 | enabled: false,
|
16 | releaseOnEdges: false,
|
17 | invert: false,
|
18 | forceToAxis: false,
|
19 | sensitivity: 1,
|
20 | eventsTarget: 'container',
|
21 | thresholdDelta: null,
|
22 | thresholdTime: null
|
23 | }
|
24 | });
|
25 | swiper.mousewheel = {
|
26 | enabled: false
|
27 | };
|
28 | let timeout;
|
29 | let lastScrollTime = now();
|
30 | let lastEventBeforeSnap;
|
31 | const recentWheelEvents = [];
|
32 |
|
33 | function normalize(e) {
|
34 |
|
35 | const PIXEL_STEP = 10;
|
36 | const LINE_HEIGHT = 40;
|
37 | const PAGE_HEIGHT = 800;
|
38 | let sX = 0;
|
39 | let sY = 0;
|
40 |
|
41 | let pX = 0;
|
42 | let pY = 0;
|
43 |
|
44 |
|
45 | if ('detail' in e) {
|
46 | sY = e.detail;
|
47 | }
|
48 |
|
49 | if ('wheelDelta' in e) {
|
50 | sY = -e.wheelDelta / 120;
|
51 | }
|
52 |
|
53 | if ('wheelDeltaY' in e) {
|
54 | sY = -e.wheelDeltaY / 120;
|
55 | }
|
56 |
|
57 | if ('wheelDeltaX' in e) {
|
58 | sX = -e.wheelDeltaX / 120;
|
59 | }
|
60 |
|
61 |
|
62 | if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
|
63 | sX = sY;
|
64 | sY = 0;
|
65 | }
|
66 |
|
67 | pX = sX * PIXEL_STEP;
|
68 | pY = sY * PIXEL_STEP;
|
69 |
|
70 | if ('deltaY' in e) {
|
71 | pY = e.deltaY;
|
72 | }
|
73 |
|
74 | if ('deltaX' in e) {
|
75 | pX = e.deltaX;
|
76 | }
|
77 |
|
78 | if (e.shiftKey && !pX) {
|
79 |
|
80 | pX = pY;
|
81 | pY = 0;
|
82 | }
|
83 |
|
84 | if ((pX || pY) && e.deltaMode) {
|
85 | if (e.deltaMode === 1) {
|
86 |
|
87 | pX *= LINE_HEIGHT;
|
88 | pY *= LINE_HEIGHT;
|
89 | } else {
|
90 |
|
91 | pX *= PAGE_HEIGHT;
|
92 | pY *= PAGE_HEIGHT;
|
93 | }
|
94 | }
|
95 |
|
96 |
|
97 | if (pX && !sX) {
|
98 | sX = pX < 1 ? -1 : 1;
|
99 | }
|
100 |
|
101 | if (pY && !sY) {
|
102 | sY = pY < 1 ? -1 : 1;
|
103 | }
|
104 |
|
105 | return {
|
106 | spinX: sX,
|
107 | spinY: sY,
|
108 | pixelX: pX,
|
109 | pixelY: pY
|
110 | };
|
111 | }
|
112 |
|
113 | function handleMouseEnter() {
|
114 | if (!swiper.enabled) return;
|
115 | swiper.mouseEntered = true;
|
116 | }
|
117 |
|
118 | function handleMouseLeave() {
|
119 | if (!swiper.enabled) return;
|
120 | swiper.mouseEntered = false;
|
121 | }
|
122 |
|
123 | function animateSlider(newEvent) {
|
124 | if (swiper.params.mousewheel.thresholdDelta && newEvent.delta < swiper.params.mousewheel.thresholdDelta) {
|
125 |
|
126 | return false;
|
127 | }
|
128 |
|
129 | if (swiper.params.mousewheel.thresholdTime && now() - lastScrollTime < swiper.params.mousewheel.thresholdTime) {
|
130 |
|
131 | return false;
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | if (newEvent.delta >= 6 && now() - lastScrollTime < 60) {
|
138 |
|
139 | return true;
|
140 | }
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | if (newEvent.direction < 0) {
|
155 | if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
|
156 | swiper.slideNext();
|
157 | emit('scroll', newEvent.raw);
|
158 | }
|
159 | } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
|
160 | swiper.slidePrev();
|
161 | emit('scroll', newEvent.raw);
|
162 | }
|
163 |
|
164 |
|
165 | lastScrollTime = new window.Date().getTime();
|
166 |
|
167 | return false;
|
168 | }
|
169 |
|
170 | function releaseScroll(newEvent) {
|
171 | const params = swiper.params.mousewheel;
|
172 |
|
173 | if (newEvent.direction < 0) {
|
174 | if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) {
|
175 |
|
176 | return true;
|
177 | }
|
178 | } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) {
|
179 |
|
180 | return true;
|
181 | }
|
182 |
|
183 | return false;
|
184 | }
|
185 |
|
186 | function handle(event) {
|
187 | let e = event;
|
188 | let disableParentSwiper = true;
|
189 | if (!swiper.enabled) return;
|
190 | const params = swiper.params.mousewheel;
|
191 |
|
192 | if (swiper.params.cssMode) {
|
193 | e.preventDefault();
|
194 | }
|
195 |
|
196 | let target = swiper.$el;
|
197 |
|
198 | if (swiper.params.mousewheel.eventsTarget !== 'container') {
|
199 | target = $(swiper.params.mousewheel.eventsTarget);
|
200 | }
|
201 |
|
202 | if (!swiper.mouseEntered && !target[0].contains(e.target) && !params.releaseOnEdges) return true;
|
203 | if (e.originalEvent) e = e.originalEvent;
|
204 |
|
205 | let delta = 0;
|
206 | const rtlFactor = swiper.rtlTranslate ? -1 : 1;
|
207 | const data = normalize(e);
|
208 |
|
209 | if (params.forceToAxis) {
|
210 | if (swiper.isHorizontal()) {
|
211 | if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true;
|
212 | } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true;
|
213 | } else {
|
214 | delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
|
215 | }
|
216 |
|
217 | if (delta === 0) return true;
|
218 | if (params.invert) delta = -delta;
|
219 |
|
220 | let positions = swiper.getTranslate() + delta * params.sensitivity;
|
221 | if (positions >= swiper.minTranslate()) positions = swiper.minTranslate();
|
222 | if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate();
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 | disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate());
|
231 | if (disableParentSwiper && swiper.params.nested) e.stopPropagation();
|
232 |
|
233 | if (!swiper.params.freeMode || !swiper.params.freeMode.enabled) {
|
234 |
|
235 | const newEvent = {
|
236 | time: now(),
|
237 | delta: Math.abs(delta),
|
238 | direction: Math.sign(delta),
|
239 | raw: event
|
240 | };
|
241 |
|
242 | if (recentWheelEvents.length >= 2) {
|
243 | recentWheelEvents.shift();
|
244 | }
|
245 |
|
246 | const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
|
247 | recentWheelEvents.push(newEvent);
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 | if (prevEvent) {
|
255 | if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) {
|
256 | animateSlider(newEvent);
|
257 | }
|
258 | } else {
|
259 | animateSlider(newEvent);
|
260 | }
|
261 |
|
262 |
|
263 |
|
264 | if (releaseScroll(newEvent)) {
|
265 | return true;
|
266 | }
|
267 | } else {
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 | const newEvent = {
|
274 | time: now(),
|
275 | delta: Math.abs(delta),
|
276 | direction: Math.sign(delta)
|
277 | };
|
278 | const ignoreWheelEvents = lastEventBeforeSnap && newEvent.time < lastEventBeforeSnap.time + 500 && newEvent.delta <= lastEventBeforeSnap.delta && newEvent.direction === lastEventBeforeSnap.direction;
|
279 |
|
280 | if (!ignoreWheelEvents) {
|
281 | lastEventBeforeSnap = undefined;
|
282 |
|
283 | if (swiper.params.loop) {
|
284 | swiper.loopFix();
|
285 | }
|
286 |
|
287 | let position = swiper.getTranslate() + delta * params.sensitivity;
|
288 | const wasBeginning = swiper.isBeginning;
|
289 | const wasEnd = swiper.isEnd;
|
290 | if (position >= swiper.minTranslate()) position = swiper.minTranslate();
|
291 | if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();
|
292 | swiper.setTransition(0);
|
293 | swiper.setTranslate(position);
|
294 | swiper.updateProgress();
|
295 | swiper.updateActiveIndex();
|
296 | swiper.updateSlidesClasses();
|
297 |
|
298 | if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) {
|
299 | swiper.updateSlidesClasses();
|
300 | }
|
301 |
|
302 | if (swiper.params.freeMode.sticky) {
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 | clearTimeout(timeout);
|
315 | timeout = undefined;
|
316 |
|
317 | if (recentWheelEvents.length >= 15) {
|
318 | recentWheelEvents.shift();
|
319 | }
|
320 |
|
321 | const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
|
322 | const firstEvent = recentWheelEvents[0];
|
323 | recentWheelEvents.push(newEvent);
|
324 |
|
325 | if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) {
|
326 |
|
327 | recentWheelEvents.splice(0);
|
328 | } else if (recentWheelEvents.length >= 15 && newEvent.time - firstEvent.time < 500 && firstEvent.delta - newEvent.delta >= 1 && newEvent.delta <= 6) {
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 | const snapToThreshold = delta > 0 ? 0.8 : 0.2;
|
336 | lastEventBeforeSnap = newEvent;
|
337 | recentWheelEvents.splice(0);
|
338 | timeout = nextTick(() => {
|
339 | swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
|
340 | }, 0);
|
341 | }
|
342 |
|
343 | if (!timeout) {
|
344 |
|
345 |
|
346 |
|
347 | timeout = nextTick(() => {
|
348 | const snapToThreshold = 0.5;
|
349 | lastEventBeforeSnap = newEvent;
|
350 | recentWheelEvents.splice(0);
|
351 | swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
|
352 | }, 500);
|
353 | }
|
354 | }
|
355 |
|
356 |
|
357 | if (!ignoreWheelEvents) emit('scroll', e);
|
358 |
|
359 | if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) swiper.autoplay.stop();
|
360 |
|
361 | if (position === swiper.minTranslate() || position === swiper.maxTranslate()) return true;
|
362 | }
|
363 | }
|
364 |
|
365 | if (e.preventDefault) e.preventDefault();else e.returnValue = false;
|
366 | return false;
|
367 | }
|
368 |
|
369 | function events(method) {
|
370 | let target = swiper.$el;
|
371 |
|
372 | if (swiper.params.mousewheel.eventsTarget !== 'container') {
|
373 | target = $(swiper.params.mousewheel.eventsTarget);
|
374 | }
|
375 |
|
376 | target[method]('mouseenter', handleMouseEnter);
|
377 | target[method]('mouseleave', handleMouseLeave);
|
378 | target[method]('wheel', handle);
|
379 | }
|
380 |
|
381 | function enable() {
|
382 | if (swiper.params.cssMode) {
|
383 | swiper.wrapperEl.removeEventListener('wheel', handle);
|
384 | return true;
|
385 | }
|
386 |
|
387 | if (swiper.mousewheel.enabled) return false;
|
388 | events('on');
|
389 | swiper.mousewheel.enabled = true;
|
390 | return true;
|
391 | }
|
392 |
|
393 | function disable() {
|
394 | if (swiper.params.cssMode) {
|
395 | swiper.wrapperEl.addEventListener(event, handle);
|
396 | return true;
|
397 | }
|
398 |
|
399 | if (!swiper.mousewheel.enabled) return false;
|
400 | events('off');
|
401 | swiper.mousewheel.enabled = false;
|
402 | return true;
|
403 | }
|
404 |
|
405 | on('init', () => {
|
406 | if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
|
407 | disable();
|
408 | }
|
409 |
|
410 | if (swiper.params.mousewheel.enabled) enable();
|
411 | });
|
412 | on('destroy', () => {
|
413 | if (swiper.params.cssMode) {
|
414 | enable();
|
415 | }
|
416 |
|
417 | if (swiper.mousewheel.enabled) disable();
|
418 | });
|
419 | Object.assign(swiper.mousewheel, {
|
420 | enable,
|
421 | disable
|
422 | });
|
423 | } |
\ | No newline at end of file |