Przeglądaj źródła

Add `wheel.min` and `wheel.sleep` options for inertia scroll.

NaotoshiFujita 3 lat temu
rodzic
commit
7fdd1cf999

+ 14 - 5
dist/js/splide.cjs.js

@@ -294,6 +294,10 @@ function removeClass(elm, classes) {
   toggleClass(elm, classes, false);
 }
 
+function timeOf(e) {
+  return e.timeStamp;
+}
+
 function unit(value) {
   return isString(value) ? value : value ? `${value}px` : "";
 }
@@ -1878,7 +1882,7 @@ function Drag(Splide2, Components2, options) {
     return coordOf(e, orthogonal) - coordOf(getBaseEvent(e), orthogonal);
   }
   function diffTime(e) {
-    return e.timeStamp - getBaseEvent(e).timeStamp;
+    return timeOf(e) - timeOf(getBaseEvent(e));
   }
   function getBaseEvent(e) {
     return baseEvent === e && prevBaseEvent || baseEvent;
@@ -2196,19 +2200,24 @@ function Sync(Splide2, Components2, options) {
 
 function Wheel(Splide2, Components2, options) {
   const { bind } = EventInterface(Splide2);
+  const { wheel: wheelOption } = options;
+  const wheel = isObject(wheelOption) ? wheelOption : wheelOption && {};
+  let lastTime = 0;
   function mount() {
-    if (options.wheel) {
+    if (wheel) {
       bind(Components2.Elements.track, "wheel", onWheel, SCROLL_LISTENER_OPTIONS);
     }
   }
   function onWheel(e) {
     if (e.cancelable) {
       const { deltaY } = e;
-      if (deltaY) {
-        const backwards = deltaY < 0;
+      const backwards = deltaY < 0;
+      const timeStamp = timeOf(e);
+      if (abs(deltaY) > (wheel.min || 0) && timeStamp - lastTime > (wheel.sleep || 0)) {
         Splide2.go(backwards ? "<" : ">");
-        shouldPrevent(backwards) && prevent(e);
+        lastTime = timeStamp;
       }
+      shouldPrevent(backwards) && prevent(e);
     }
   }
   function shouldPrevent(backwards) {

+ 14 - 5
dist/js/splide.esm.js

@@ -290,6 +290,10 @@ function removeClass(elm, classes) {
   toggleClass(elm, classes, false);
 }
 
+function timeOf(e) {
+  return e.timeStamp;
+}
+
 function unit(value) {
   return isString(value) ? value : value ? `${value}px` : "";
 }
@@ -1874,7 +1878,7 @@ function Drag(Splide2, Components2, options) {
     return coordOf(e, orthogonal) - coordOf(getBaseEvent(e), orthogonal);
   }
   function diffTime(e) {
-    return e.timeStamp - getBaseEvent(e).timeStamp;
+    return timeOf(e) - timeOf(getBaseEvent(e));
   }
   function getBaseEvent(e) {
     return baseEvent === e && prevBaseEvent || baseEvent;
@@ -2192,19 +2196,24 @@ function Sync(Splide2, Components2, options) {
 
 function Wheel(Splide2, Components2, options) {
   const { bind } = EventInterface(Splide2);
+  const { wheel: wheelOption } = options;
+  const wheel = isObject(wheelOption) ? wheelOption : wheelOption && {};
+  let lastTime = 0;
   function mount() {
-    if (options.wheel) {
+    if (wheel) {
       bind(Components2.Elements.track, "wheel", onWheel, SCROLL_LISTENER_OPTIONS);
     }
   }
   function onWheel(e) {
     if (e.cancelable) {
       const { deltaY } = e;
-      if (deltaY) {
-        const backwards = deltaY < 0;
+      const backwards = deltaY < 0;
+      const timeStamp = timeOf(e);
+      if (abs(deltaY) > (wheel.min || 0) && timeStamp - lastTime > (wheel.sleep || 0)) {
         Splide2.go(backwards ? "<" : ">");
-        shouldPrevent(backwards) && prevent(e);
+        lastTime = timeStamp;
       }
+      shouldPrevent(backwards) && prevent(e);
     }
   }
   function shouldPrevent(backwards) {

+ 16 - 5
dist/js/splide.js

@@ -319,6 +319,10 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     toggleClass(elm, classes, false);
   }
 
+  function timeOf(e) {
+    return e.timeStamp;
+  }
+
   function unit(value) {
     return isString(value) ? value : value ? value + "px" : "";
   }
@@ -2243,7 +2247,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function diffTime(e) {
-      return e.timeStamp - getBaseEvent(e).timeStamp;
+      return timeOf(e) - timeOf(getBaseEvent(e));
     }
 
     function getBaseEvent(e) {
@@ -2662,8 +2666,12 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var _EventInterface16 = EventInterface(Splide2),
         bind = _EventInterface16.bind;
 
+    var wheelOption = options.wheel;
+    var wheel = isObject(wheelOption) ? wheelOption : wheelOption && {};
+    var lastTime = 0;
+
     function mount() {
-      if (options.wheel) {
+      if (wheel) {
         bind(Components2.Elements.track, "wheel", onWheel, SCROLL_LISTENER_OPTIONS);
       }
     }
@@ -2671,12 +2679,15 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function onWheel(e) {
       if (e.cancelable) {
         var deltaY = e.deltaY;
+        var backwards = deltaY < 0;
+        var timeStamp = timeOf(e);
 
-        if (deltaY) {
-          var backwards = deltaY < 0;
+        if (abs(deltaY) > (wheel.min || 0) && timeStamp - lastTime > (wheel.sleep || 0)) {
           Splide2.go(backwards ? "<" : ">");
-          shouldPrevent(backwards) && prevent(e);
+          lastTime = timeStamp;
         }
+
+        shouldPrevent(backwards) && prevent(e);
       }
     }
 

Plik diff jest za duży
+ 0 - 0
dist/js/splide.js.map


Plik diff jest za duży
+ 0 - 0
dist/js/splide.min.js


BIN
dist/js/splide.min.js.gz


Plik diff jest za duży
+ 0 - 0
dist/js/splide.min.js.map


+ 13 - 3
dist/types/index.d.ts

@@ -350,9 +350,19 @@ interface Options extends ResponsiveOptions {
     keyboard?: boolean | string;
     /**
      * Enables navigation by the mouse wheel.
-     * The `waitForTransition` option should be `true`.
-     */
-    wheel?: boolean;
+     * Set `waitForTransition` to `ture` or provide the `sleep` duration.
+     */
+    wheel?: boolean | {
+        /**
+         * The threshold to cut off the small delta produced by inertia scroll.
+         */
+        min?: number;
+        /**
+         * The sleep time in milliseconds until accepting next wheel.
+         * The timer starts when the transition begins.
+         */
+        sleep?: number;
+    };
     /**
      * Determines whether to release the wheel event when the slider reaches the first or last slide.
      */

+ 2 - 2
src/js/components/Drag/Drag.ts

@@ -5,7 +5,7 @@ import { FADE, LOOP, SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { abs, isObject, matches, min, noop, prevent, sign } from '../../utils';
+import { abs, isObject, matches, min, noop, prevent, sign, timeOf } from '../../utils';
 import { FRICTION, LOG_INTERVAL, POINTER_DOWN_EVENTS, POINTER_MOVE_EVENTS, POINTER_UP_EVENTS } from './constants';
 
 
@@ -318,7 +318,7 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
    * @return The elapsed time in milliseconds.
    */
   function diffTime( e: TouchEvent | MouseEvent ): number {
-    return e.timeStamp - getBaseEvent( e ).timeStamp;
+    return timeOf( e ) - timeOf( getBaseEvent( e ) );
   }
 
   /**

+ 15 - 5
src/js/components/Wheel/Wheel.ts

@@ -3,7 +3,7 @@ import { MOVING } from '../../constants/states';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { prevent } from '../../utils';
+import { abs, isObject, prevent, timeOf } from '../../utils';
 
 
 /**
@@ -27,12 +27,19 @@ export interface WheelComponent extends BaseComponent {
  */
 export function Wheel( Splide: Splide, Components: Components, options: Options ): WheelComponent {
   const { bind } = EventInterface( Splide );
+  const { wheel: wheelOption } = options;
+  const wheel = isObject( wheelOption ) ? wheelOption : wheelOption && {};
+
+  /**
+   * Holds the last time when the wheel moves the slider.
+   */
+  let lastTime = 0;
 
   /**
    * Called when the component is mounted.
    */
   function mount(): void {
-    if ( options.wheel ) {
+    if ( wheel ) {
       bind( Components.Elements.track, 'wheel', onWheel, SCROLL_LISTENER_OPTIONS );
     }
   }
@@ -45,12 +52,15 @@ export function Wheel( Splide: Splide, Components: Components, options: Options
   function onWheel( e: WheelEvent ): void {
     if ( e.cancelable ) {
       const { deltaY } = e;
+      const backwards = deltaY < 0;
+      const timeStamp = timeOf( e );
 
-      if ( deltaY ) {
-        const backwards = deltaY < 0;
+      if ( abs( deltaY ) > ( wheel.min || 0 ) && timeStamp - lastTime > ( wheel.sleep || 0 ) ) {
         Splide.go( backwards ? '<' : '>' );
-        shouldPrevent( backwards ) && prevent( e );
+        lastTime = timeStamp;
       }
+
+      shouldPrevent( backwards ) && prevent( e );
     }
   }
 

+ 1 - 1
src/js/components/Wheel/test/general.test.ts

@@ -37,7 +37,7 @@ describe( 'Wheel', () => {
   } );
 } );
 
-function fireCancelable( elm: Element | Window, event: string, data: any = {} ): void {
+export function fireCancelable( elm: Element | Window, event: string, data: any = {} ): void {
   fire( elm, event, data, { cancelable: true } );
 }
 

+ 46 - 0
src/js/components/Wheel/test/inertia.test.ts

@@ -0,0 +1,46 @@
+import { init } from '../../../test';
+import { fireCancelable } from './general.test';
+
+
+describe( 'Wheel', () => {
+  test( 'should move the slider only when the delta is greater than the min threshold.', () => {
+    const splide = init( { speed: 0, wheel: { min: 50 } } );
+    const { track } = splide.Components.Elements;
+
+    fireCancelable( track, 'wheel', { deltaY: 49 } );
+    expect( splide.index ).toBe( 0 );
+
+    fireCancelable( track, 'wheel', { deltaY: 50 } );
+    expect( splide.index ).toBe( 0 );
+
+    fireCancelable( track, 'wheel', { deltaY: 51 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: -49 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: -50 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: -51 } );
+    expect( splide.index ).toBe( 0 );
+  } );
+
+  test( 'should not move the slider while the wheel component is sleeping.', () => {
+    const splide = init( { speed: 0, wheel: { sleep: 500 } } );
+    const { track } = splide.Components.Elements;
+
+    fireCancelable( track, 'wheel', { deltaY: 100, timeStamp: 1000 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: 100, timeStamp: 1100 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: 100, timeStamp: 1500 } );
+    expect( splide.index ).toBe( 1 );
+
+    fireCancelable( track, 'wheel', { deltaY: 100, timeStamp: 1501 } );
+    expect( splide.index ).toBe( 2 );
+  } );
+} );
+

+ 5 - 1
src/js/test/php/examples/ttb.php

@@ -27,8 +27,12 @@ $settings = get_settings();
         direction   : 'ttb',
         height      : '90vh',
         cover       : true,
-        wheel       : true,
+        // wheel       : true,
         releaseWheel: true,
+	      wheel       : {
+					// min: 99,
+		      sleep: 500,
+	      },
       } );
 
       splide.mount();

+ 14 - 3
src/js/types/options.ts

@@ -104,9 +104,20 @@ export interface Options extends ResponsiveOptions {
 
   /**
    * Enables navigation by the mouse wheel.
-   * The `waitForTransition` option should be `true`.
-   */
-  wheel?: boolean;
+   * Set `waitForTransition` to `ture` or provide the `sleep` duration.
+   */
+  wheel?: boolean | {
+    /**
+     * The threshold to cut off the small delta produced by inertia scroll.
+     */
+    min?: number,
+
+    /**
+     * The sleep time in milliseconds until accepting next wheel.
+     * The timer starts when the transition begins.
+     */
+    sleep?: number,
+  };
 
   /**
    * Determines whether to release the wheel event when the slider reaches the first or last slide.

+ 1 - 0
src/js/utils/dom/index.ts

@@ -20,5 +20,6 @@ export { removeAttribute } from './removeAttribute/removeAttribute';
 export { removeClass }     from './removeClass/removeClass';
 export { setAttribute }    from './setAttribute/setAttribute';
 export { style }           from './style/style';
+export { timeOf }          from './timeOf/timeOf';
 export { toggleClass }     from './toggleClass/toggleClass';
 export { unit }            from './unit/unit';

+ 15 - 0
src/js/utils/dom/prevent/prevent.test.ts

@@ -0,0 +1,15 @@
+import { fire } from '../../../test';
+import { prevent } from './prevent';
+
+
+describe( 'prevent', () => {
+  test( 'can prevent the default browser action of an event.', done => {
+    window.addEventListener( 'click', e => {
+      prevent( e );
+      expect( e.defaultPrevented ).toBe( true );
+      done();
+    } );
+
+    fire( window, 'click', { timeStamp: 123 }, { cancelable: true } );
+  } );
+} );

+ 14 - 0
src/js/utils/dom/timeOf/timeOf.test.ts

@@ -0,0 +1,14 @@
+import { fire } from '../../../test';
+import { timeOf } from './timeOf';
+
+
+describe( 'timeOf', () => {
+  test( 'can extract a timestamp from an event object.', done => {
+    window.addEventListener( 'click', e => {
+      expect( timeOf( e ) ).toBe( 123 );
+      done();
+    } );
+
+    fire( window, 'click', { timeStamp: 123 } );
+  } );
+} );

+ 8 - 0
src/js/utils/dom/timeOf/timeOf.ts

@@ -0,0 +1,8 @@
+/**
+ * Extracts the timestamp from the event object.
+ *
+ * @param e - An Event object.
+ */
+export function timeOf( e: Event ): number {
+  return e.timeStamp;
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików