123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- import { Components, Options, RequestIntervalInterface, ScrollComponent } from '@splidejs/splide';
- import { EVENT_MOVE, EVENT_REFRESH, EVENT_SCROLL, EVENT_SCROLLED, EVENT_UPDATED } from '../../constants/events';
- import { SLIDE } from '../../constants/types';
- import { EventInterface, RequestInterval } from '../../constructors';
- import { Splide } from '../../core/Splide/Splide';
- import { abs, max } from '../../utils';
- import { BASE_VELOCITY, BOUNCE_DIFF_THRESHOLD, BOUNCE_DURATION, FRICTION_FACTOR, MIN_DURATION } from './constants';
- /**
- * The component for scrolling the slider.
- *
- * @since 3.0.0
- *
- * @param Splide - A Splide instance.
- * @param Components - A collection of components.
- * @param options - Options.
- *
- * @return A Scroll component object.
- */
- export function Scroll( Splide: Splide, Components: Components, options: Options ): ScrollComponent {
- const { on, emit } = EventInterface( Splide );
- const { Move } = Components;
- const { getPosition, getLimit } = Move;
- /**
- * Retains the active RequestInterval object.
- */
- let interval: RequestIntervalInterface;
- /**
- * Called when the component is mounted.
- */
- function mount(): void {
- on( EVENT_MOVE, clear );
- on( [ EVENT_UPDATED, EVENT_REFRESH ], cancel );
- }
- /**
- * Scrolls the slider to the provided destination.
- *
- * @param destination - The destination to scroll to.
- * @param duration - Optional. The scroll duration. If omitted, calculates it by the distance.
- * @param suppressConstraint - Optional. Whether to suppress constraint process when the slider exceeds bounds.
- */
- function scroll( destination: number, duration?: number, suppressConstraint?: boolean ): void {
- const start = getPosition();
- let friction = 1;
- duration = duration || computeDuration( abs( destination - start ) );
- clear();
- interval = RequestInterval( duration, onScrolled, rate => {
- const position = getPosition();
- const target = start + ( destination - start ) * easing( rate );
- const diff = ( target - getPosition() ) * friction;
- Move.translate( position + diff );
- if ( Splide.is( SLIDE ) && ! suppressConstraint && Move.isExceeded() ) {
- friction *= FRICTION_FACTOR;
- if ( abs( diff ) < BOUNCE_DIFF_THRESHOLD ) {
- bounce( Move.isExceededMin( getPosition() ) );
- }
- }
- }, 1 );
- emit( EVENT_SCROLL );
- interval.start();
- }
- /**
- * Triggers the bounce effect when the slider reaches bounds.
- *
- * @param backwards - The direction the slider is going towards.
- */
- function bounce( backwards: boolean ): void {
- scroll( getLimit( ! backwards ), BOUNCE_DURATION, true );
- }
- /**
- * Called when scroll ends or is canceled.
- */
- function onScrolled(): void {
- emit( EVENT_SCROLLED );
- }
- /**
- * Computes the scroll duration by the distance and the base velocity.
- *
- * @param distance - Distance in pixel.
- *
- * @return The duration for scroll.
- */
- function computeDuration( distance: number ): number {
- return max( distance / BASE_VELOCITY, MIN_DURATION );
- }
- /**
- * Clears the active interval.
- */
- function clear(): void {
- if ( interval ) {
- interval.cancel();
- }
- }
- /**
- * Cancels the active interval and emits the `scrolled` event.
- */
- function cancel(): void {
- if ( interval && ! interval.isPaused() ) {
- clear();
- onScrolled();
- }
- }
- /**
- * The easing function.
- *
- * @param t - A value to ease.
- *
- * @return An eased value.
- */
- function easing( t: number ): number {
- const { easingFunc } = options;
- return easingFunc ? easingFunc( t ) : 1 - Math.pow( 1 - t, 4 );
- }
- return {
- mount,
- destroy: clear,
- scroll,
- cancel,
- };
- }
|