Как исправить конфликты событий между Swiper и Video.Js

Я использую Swiper для простого слайд-шоу с изображениями и видео. Это работает как шарм. Однако, поскольку требование к дизайну состоит в том, чтобы иметь согласованный и красивый пользовательский интерфейс проигрывателя, мне нужно использовать Video.js в качестве видеопроигрывателя. Итак, у меня есть Swiper в качестве плагина для слайд-шоу и Video.js в качестве видео-плагина. Это работает, за исключением того, что между этими двумя плагинами возникают конфликты событий.

Swiper имеет событие mousedown в своем корне, в то время как Video.js также имеет событие mousedown для видео и его (динамически созданного Video.js) родительского контейнера. При перетаскивании слайда (видео) не только Swiper определяет, что он должен провести пальцем, но и Video.js будет обрабатывать это как щелчок по видео. Поэтому, если вы переходите к следующему слайду, это всегда означает, что видео воспроизводится/приостанавливается.

Кроме того, когда вы перетаскиваете круг на временной шкале, Swiper также обнаруживает смахивание.

Есть ли возможность исправить оба обработчика событий для совместной работы? Я ищу способ без исправления самих библиотек. Также патч не должен влиять на исходное поведение плагинов.

Вот код, на который я ссылаюсь. Вы также можете поиграть с этим jsfiddle.

var swiper = new Swiper('.swiper-container', {
  pagination: '.swiper-pagination',
  paginationClickable: true,
  nextButton: '.swiper-button-next',
  prevButton: '.swiper-button-prev',
  spaceBetween: 30
});

[...document.querySelectorAll('video')].forEach(video => {
  video.classList.add('video-js');
  video.classList.add('vjs-default-skin');
  video.classList.add('vjs-big-play-centered');
  videojs(video, {
    fluid: true,
    autoplay: true
  });
});
html,
body {
  position: relative;
  height: 100%;
}

body {
  background: #eee;
  font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
  font-size: 14px;
  color: #000;
  margin: 0;
  padding: 0;
}

.swiper-container {
  width: 100%;
  height: 100%;
}

.swiper-slide {
  text-align: center;
  font-size: 18px;
  background: #fff;
  /* Center slide text vertically */
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.2.5/video-js.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.2.5/video.min.js"></script>

<!-- Swiper -->
<div class="swiper-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      <video preload="auto" muted loop controls>
        <source src="https://dwknz3zfy9iu1.cloudfront.net/uscenes_h-264_hd_test.mp4" type="video/mp4">
      </video>
    </div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">
      <video preload="auto" muted loop controls>
        <source src="https://dwknz3zfy9iu1.cloudfront.net/uscenes_h-264_hd_test.mp4" type="video/mp4">
      </video>
    </div>
    <div class="swiper-slide">Slide 4</div>
    <div class="swiper-slide">Slide 5</div>
    <div class="swiper-slide">Slide 6</div>
    <div class="swiper-slide">Slide 7</div>
    <div class="swiper-slide">Slide 8</div>
    <div class="swiper-slide">Slide 9</div>
    <div class="swiper-slide">Slide 10</div>
  </div>
  <!-- Add Pagination -->
  <div class="swiper-pagination"></div>
  <!-- Add Arrows -->
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>


person dude    schedule 02.08.2017    source источник


Ответы (3)


Другой подход, но более соответствующий тому, что вы просите, заключается в добавлении наложения поверх видео и передаче только событий кликов в видео.

Он растягивает оверлей до размера области видео, исключая панель управления видео внизу.

В div панели управления добавьте класс 'swiper-no-swiping', чтобы Swiper не распознавал видеожесты.

Теперь свайп по оверлею не приведет к воспроизведению или паузе видео, но щелчок по нему и жесты на панели управления видео будут игнорироваться Swiper.

Конечно, видимый CSS и текст служат только для иллюстрации наложения и будут удалены.

var swiper = new Swiper('.swiper-container', {
  pagination: '.swiper-pagination',
  paginationClickable: true,
  nextButton: '.swiper-button-next',
  prevButton: '.swiper-button-prev',
  spaceBetween: 30,
  noSwipingClass: 'swiper-no-swiping'
});

[...document.querySelectorAll('video')].forEach(video => {
  video.classList.add('video-js');
  video.classList.add('vjs-default-skin');
  video.classList.add('vjs-big-play-centered');
  videojs(video, {
    fluid: true,
    autoplay: true
  });
});

$(function() {

  var $overlay = $("#video-overlay1");
  var myPlayer = videojs('vid1');
  var $overlayArea = $("#vid1 > .vjs-text-track-display");

  // apply overlay on video to prevent swipes playing/pausing the video
  positionVideoOverlay();

  // prevent swiping action on video control bar
  $(".vjs-control-bar").addClass("swiper-no-swiping");

  $overlay.click(function() {
    if (myPlayer.paused())
      myPlayer.play();
    else
      myPlayer.pause();
  });

  $(window).resize(function() {
    positionVideoOverlay();
  });

  function positionVideoOverlay() {
    $overlay.css("width", $overlayArea.width() + "px");
    $overlay.css("height", $overlayArea.height() + "px");
    $overlay.css("top", $overlayArea.offset().top + "px")
  }
});
.video-overlay {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 20px;
  font-family: Helvetica;
  color: #FFF;
  background-color: rgba(50, 50, 50, 0.8);
}
<div class="swiper-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      <video id="vid1" preload="auto" muted loop controls>
            <source src="https://dwknz3zfy9iu1.cloudfront.net/uscenes_h-264_hd_test.mp4" type="video/mp4">
          </video>
      <div id="video-overlay1" class="video-overlay">Overlay that will pass clicks to video layer
        <br>But will not pass swipe gestures</div>
    </div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
  </div>
  <!-- Add Pagination -->
  <div class="swiper-pagination"></div>
  <!-- Add Arrows -->
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>

Демонстрация, иллюстрирующая основную концепцию: https://jsfiddle.net/1vqozv25/4/

person K Scandrett    schedule 06.08.2017
comment
Хотя это работает с реальным видео, оно не работает с видеоплеером. Как вы можете видеть в в этом примере, если вы расположите наложенный элемент div так, чтобы он полностью накладывался на видео, нажимает кнопку отключения звука или полноэкранного режима, иначе временная шкала ничего не сделает. Также вы не можете перетаскивать круг временной шкалы, как в других примерах Video.js. Одним из требований было: the patch should not affect the original behavior of the plugins. - person dude; 06.08.2017
comment
Вот почему я сказал, исключая панель управления внизу. Он должен покрывать только площадь <div class="vjs-text-track-display"> - person K Scandrett; 06.08.2017
comment
Если вы исключите временную шкалу из наложения, у нас будут те же проблемы, что и раньше: Если вы перетащите круг на временной шкале, Swiper скользит. - person dude; 06.08.2017
comment
Отредактировал мой ответ. Он добавляет класс noSwipingClass: 'swiper-no-swiping' на панель управления видео и устанавливает высоту и положение наложения. jsfiddle.net/1vqozv25/3 - person K Scandrett; 06.08.2017
comment
Добавлен код для настройки наложения при изменении размера окна — jsfiddle.net/1vqozv25/4. - person K Scandrett; 06.08.2017
comment
Новые улучшения изменения размера не работают для меня: imgur.com/a/cKudc - person dude; 06.08.2017
comment
Вы можете попробовать переместить var $overlayArea = $("#vid1 > .vjs-text-track-display"); в функцию. Я написал это больше как демонстрацию принципов, а не как окончательный код, поэтому вам нужно будет его подправить здесь и там. - person K Scandrett; 06.08.2017
comment
Если подумать... лучше установить высоту наложения равной высоте видео минус высота панели управления: $("#vid1 > video").height() - $("#vid1 > .vjs-control-bar").height(). Я подозреваю, что высота элемента, который я использовал, не точно установлена ​​Video.js при изменении размера. Также я бы не стал переносить этот код в функцию - это вообще не поможет, но снизит производительность. - person K Scandrett; 07.08.2017

Вы можете добавить класс к опции noSwipingClass, чтобы запретить Swiper обрабатывать события на слайдах с этим классом. Теперь на слайдах видео будут работать только кнопки «следующий/предыдущий». Возможно разумный компромисс.

eg.

var swiper = new Swiper('.swiper-container', {
  nextButton: '.swiper-button-next',
  prevButton: '.swiper-button-prev',
  spaceBetween: 30,
  noSwipingClass: 'swiper-no-swiping'
});

с участием:

<!-- Swiper -->
<div class="swiper-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide swiper-no-swiping" oncouseo>
      <video preload="auto" muted loop controls>
        <source src="https://dwknz3zfy9iu1.cloudfront.net/uscenes_h-264_hd_test.mp4" type="video/mp4">
      </video>
    </div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide swiper-no-swiping">
      <video preload="auto" muted loop controls>
        <source src="https://dwknz3zfy9iu1.cloudfront.net/uscenes_h-264_hd_test.mp4" type="video/mp4">
      </video>
    </div>
    <div class="swiper-slide">Slide 4</div>
    <div class="swiper-slide">Slide 5</div>
  </div>
  <!-- Add Arrows -->
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>

Демонстрация: https://jsfiddle.net/zqhLqfck/

person K Scandrett    schedule 05.08.2017
comment
Спасибо! Я подожду, если у кого-то еще будет другой подход, который все еще позволяет проводить свайпы. - person dude; 05.08.2017

Это не установит swiper только для панели управления видео js.

$(.vjs-control-bar).addClass('swiper-no-swiping');

Свайп по-прежнему работает на видео div.

person Todor Manev    schedule 15.03.2021