279 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
/* eslint no-underscore-dangle: "off" */
 | 
						|
/* eslint no-use-before-define: "off" */
 | 
						|
import { getDocument } from 'ssr-window';
 | 
						|
export default function Autoplay({
 | 
						|
  swiper,
 | 
						|
  extendParams,
 | 
						|
  on,
 | 
						|
  emit,
 | 
						|
  params
 | 
						|
}) {
 | 
						|
  swiper.autoplay = {
 | 
						|
    running: false,
 | 
						|
    paused: false,
 | 
						|
    timeLeft: 0
 | 
						|
  };
 | 
						|
  extendParams({
 | 
						|
    autoplay: {
 | 
						|
      enabled: false,
 | 
						|
      delay: 3000,
 | 
						|
      waitForTransition: true,
 | 
						|
      disableOnInteraction: true,
 | 
						|
      stopOnLastSlide: false,
 | 
						|
      reverseDirection: false,
 | 
						|
      pauseOnMouseEnter: false
 | 
						|
    }
 | 
						|
  });
 | 
						|
  let timeout;
 | 
						|
  let raf;
 | 
						|
  let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000;
 | 
						|
  let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000;
 | 
						|
  let autoplayTimeLeft;
 | 
						|
  let autoplayStartTime = new Date().getTime;
 | 
						|
  let wasPaused;
 | 
						|
  let isTouched;
 | 
						|
  let pausedByTouch;
 | 
						|
  let touchStartTimeout;
 | 
						|
  let slideChanged;
 | 
						|
  let pausedByInteraction;
 | 
						|
  function onTransitionEnd(e) {
 | 
						|
    if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
 | 
						|
    if (e.target !== swiper.wrapperEl) return;
 | 
						|
    swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
 | 
						|
    resume();
 | 
						|
  }
 | 
						|
  const calcTimeLeft = () => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    if (swiper.autoplay.paused) {
 | 
						|
      wasPaused = true;
 | 
						|
    } else if (wasPaused) {
 | 
						|
      autoplayDelayCurrent = autoplayTimeLeft;
 | 
						|
      wasPaused = false;
 | 
						|
    }
 | 
						|
    const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime();
 | 
						|
    swiper.autoplay.timeLeft = timeLeft;
 | 
						|
    emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal);
 | 
						|
    raf = requestAnimationFrame(() => {
 | 
						|
      calcTimeLeft();
 | 
						|
    });
 | 
						|
  };
 | 
						|
  const getSlideDelay = () => {
 | 
						|
    let activeSlideEl;
 | 
						|
    if (swiper.virtual && swiper.params.virtual.enabled) {
 | 
						|
      activeSlideEl = swiper.slides.filter(slideEl => slideEl.classList.contains('swiper-slide-active'))[0];
 | 
						|
    } else {
 | 
						|
      activeSlideEl = swiper.slides[swiper.activeIndex];
 | 
						|
    }
 | 
						|
    if (!activeSlideEl) return undefined;
 | 
						|
    const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10);
 | 
						|
    return currentSlideDelay;
 | 
						|
  };
 | 
						|
  const run = delayForce => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    cancelAnimationFrame(raf);
 | 
						|
    calcTimeLeft();
 | 
						|
    let delay = typeof delayForce === 'undefined' ? swiper.params.autoplay.delay : delayForce;
 | 
						|
    autoplayDelayTotal = swiper.params.autoplay.delay;
 | 
						|
    autoplayDelayCurrent = swiper.params.autoplay.delay;
 | 
						|
    const currentSlideDelay = getSlideDelay();
 | 
						|
    if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0 && typeof delayForce === 'undefined') {
 | 
						|
      delay = currentSlideDelay;
 | 
						|
      autoplayDelayTotal = currentSlideDelay;
 | 
						|
      autoplayDelayCurrent = currentSlideDelay;
 | 
						|
    }
 | 
						|
    autoplayTimeLeft = delay;
 | 
						|
    const speed = swiper.params.speed;
 | 
						|
    const proceed = () => {
 | 
						|
      if (!swiper || swiper.destroyed) return;
 | 
						|
      if (swiper.params.autoplay.reverseDirection) {
 | 
						|
        if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) {
 | 
						|
          swiper.slidePrev(speed, true, true);
 | 
						|
          emit('autoplay');
 | 
						|
        } else if (!swiper.params.autoplay.stopOnLastSlide) {
 | 
						|
          swiper.slideTo(swiper.slides.length - 1, speed, true, true);
 | 
						|
          emit('autoplay');
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) {
 | 
						|
          swiper.slideNext(speed, true, true);
 | 
						|
          emit('autoplay');
 | 
						|
        } else if (!swiper.params.autoplay.stopOnLastSlide) {
 | 
						|
          swiper.slideTo(0, speed, true, true);
 | 
						|
          emit('autoplay');
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (swiper.params.cssMode) {
 | 
						|
        autoplayStartTime = new Date().getTime();
 | 
						|
        requestAnimationFrame(() => {
 | 
						|
          run();
 | 
						|
        });
 | 
						|
      }
 | 
						|
    };
 | 
						|
    if (delay > 0) {
 | 
						|
      clearTimeout(timeout);
 | 
						|
      timeout = setTimeout(() => {
 | 
						|
        proceed();
 | 
						|
      }, delay);
 | 
						|
    } else {
 | 
						|
      requestAnimationFrame(() => {
 | 
						|
        proceed();
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    // eslint-disable-next-line
 | 
						|
    return delay;
 | 
						|
  };
 | 
						|
  const start = () => {
 | 
						|
    swiper.autoplay.running = true;
 | 
						|
    run();
 | 
						|
    emit('autoplayStart');
 | 
						|
  };
 | 
						|
  const stop = () => {
 | 
						|
    swiper.autoplay.running = false;
 | 
						|
    clearTimeout(timeout);
 | 
						|
    cancelAnimationFrame(raf);
 | 
						|
    emit('autoplayStop');
 | 
						|
  };
 | 
						|
  const pause = (internal, reset) => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    clearTimeout(timeout);
 | 
						|
    if (!internal) {
 | 
						|
      pausedByInteraction = true;
 | 
						|
    }
 | 
						|
    const proceed = () => {
 | 
						|
      emit('autoplayPause');
 | 
						|
      if (swiper.params.autoplay.waitForTransition) {
 | 
						|
        swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd);
 | 
						|
      } else {
 | 
						|
        resume();
 | 
						|
      }
 | 
						|
    };
 | 
						|
    swiper.autoplay.paused = true;
 | 
						|
    if (reset) {
 | 
						|
      if (slideChanged) {
 | 
						|
        autoplayTimeLeft = swiper.params.autoplay.delay;
 | 
						|
      }
 | 
						|
      slideChanged = false;
 | 
						|
      proceed();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    const delay = autoplayTimeLeft || swiper.params.autoplay.delay;
 | 
						|
    autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime);
 | 
						|
    if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return;
 | 
						|
    if (autoplayTimeLeft < 0) autoplayTimeLeft = 0;
 | 
						|
    proceed();
 | 
						|
  };
 | 
						|
  const resume = () => {
 | 
						|
    if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    autoplayStartTime = new Date().getTime();
 | 
						|
    if (pausedByInteraction) {
 | 
						|
      pausedByInteraction = false;
 | 
						|
      run(autoplayTimeLeft);
 | 
						|
    } else {
 | 
						|
      run();
 | 
						|
    }
 | 
						|
    swiper.autoplay.paused = false;
 | 
						|
    emit('autoplayResume');
 | 
						|
  };
 | 
						|
  const onVisibilityChange = () => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    const document = getDocument();
 | 
						|
    if (document.visibilityState === 'hidden') {
 | 
						|
      pausedByInteraction = true;
 | 
						|
      pause(true);
 | 
						|
    }
 | 
						|
    if (document.visibilityState === 'visible') {
 | 
						|
      resume();
 | 
						|
    }
 | 
						|
  };
 | 
						|
  const onPointerEnter = e => {
 | 
						|
    if (e.pointerType !== 'mouse') return;
 | 
						|
    pausedByInteraction = true;
 | 
						|
    pause(true);
 | 
						|
  };
 | 
						|
  const onPointerLeave = e => {
 | 
						|
    if (e.pointerType !== 'mouse') return;
 | 
						|
    if (swiper.autoplay.paused) {
 | 
						|
      resume();
 | 
						|
    }
 | 
						|
  };
 | 
						|
  const attachMouseEvents = () => {
 | 
						|
    if (swiper.params.autoplay.pauseOnMouseEnter) {
 | 
						|
      swiper.el.addEventListener('pointerenter', onPointerEnter);
 | 
						|
      swiper.el.addEventListener('pointerleave', onPointerLeave);
 | 
						|
    }
 | 
						|
  };
 | 
						|
  const detachMouseEvents = () => {
 | 
						|
    swiper.el.removeEventListener('pointerenter', onPointerEnter);
 | 
						|
    swiper.el.removeEventListener('pointerleave', onPointerLeave);
 | 
						|
  };
 | 
						|
  const attachDocumentEvents = () => {
 | 
						|
    const document = getDocument();
 | 
						|
    document.addEventListener('visibilitychange', onVisibilityChange);
 | 
						|
  };
 | 
						|
  const detachDocumentEvents = () => {
 | 
						|
    const document = getDocument();
 | 
						|
    document.removeEventListener('visibilitychange', onVisibilityChange);
 | 
						|
  };
 | 
						|
  on('init', () => {
 | 
						|
    if (swiper.params.autoplay.enabled) {
 | 
						|
      attachMouseEvents();
 | 
						|
      attachDocumentEvents();
 | 
						|
      autoplayStartTime = new Date().getTime();
 | 
						|
      start();
 | 
						|
    }
 | 
						|
  });
 | 
						|
  on('destroy', () => {
 | 
						|
    detachMouseEvents();
 | 
						|
    detachDocumentEvents();
 | 
						|
    if (swiper.autoplay.running) {
 | 
						|
      stop();
 | 
						|
    }
 | 
						|
  });
 | 
						|
  on('beforeTransitionStart', (_s, speed, internal) => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    if (internal || !swiper.params.autoplay.disableOnInteraction) {
 | 
						|
      pause(true, true);
 | 
						|
    } else {
 | 
						|
      stop();
 | 
						|
    }
 | 
						|
  });
 | 
						|
  on('sliderFirstMove', () => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    if (swiper.params.autoplay.disableOnInteraction) {
 | 
						|
      stop();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    isTouched = true;
 | 
						|
    pausedByTouch = false;
 | 
						|
    pausedByInteraction = false;
 | 
						|
    touchStartTimeout = setTimeout(() => {
 | 
						|
      pausedByInteraction = true;
 | 
						|
      pausedByTouch = true;
 | 
						|
      pause(true);
 | 
						|
    }, 200);
 | 
						|
  });
 | 
						|
  on('touchEnd', () => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return;
 | 
						|
    clearTimeout(touchStartTimeout);
 | 
						|
    clearTimeout(timeout);
 | 
						|
    if (swiper.params.autoplay.disableOnInteraction) {
 | 
						|
      pausedByTouch = false;
 | 
						|
      isTouched = false;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    if (pausedByTouch && swiper.params.cssMode) resume();
 | 
						|
    pausedByTouch = false;
 | 
						|
    isTouched = false;
 | 
						|
  });
 | 
						|
  on('slideChange', () => {
 | 
						|
    if (swiper.destroyed || !swiper.autoplay.running) return;
 | 
						|
    slideChanged = true;
 | 
						|
  });
 | 
						|
  Object.assign(swiper.autoplay, {
 | 
						|
    start,
 | 
						|
    stop,
 | 
						|
    pause,
 | 
						|
    resume
 | 
						|
  });
 | 
						|
} |