如何修复Swiper和Video.Js之间的事件冲突

时间:2017-08-02 18:59:44

标签: javascript event-handling mouseevent video.js swiper

我正在使用Swiper进行带有图像和视频的简单幻灯片放映。这就像一个魅力。但是,因为设计要求是拥有一致且美观的播放器UI,所以我需要将Video.js用作视频播放器。所以我将Swiper作为幻灯片插件,将Video.js作为视频插件。这是有效的,除了这两个插件之间存在事件冲突

Swiper在其根目录上有一个mousedown事件,而Video.js在视频及其(由Video.js动态创建)父容器上也有一个mousedown事件。拖动幻灯片(视频)时,不仅Swiper检测到它必须滑动,而且Video.js也会在点击视频时处理此问题。 因此,如果您滑动到下一张幻灯片,则表示视频已播放/暂停。

此外,当您在时间线上拖动圆圈时,Swiper也会检测到滑动。

有没有机会修补两个事件监听器一起工作?我正在寻找一种方法,而无需修补库本身。补丁也不应该影响插件的原始行为。

这是我正在努力的代码。您也可以使用this 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>

3 个答案:

答案 0 :(得分:2)

You can add a class to the option noSwipingClass to prevent Swiper from processing events on slides with that class. Now only the next/prev Swiper buttons will work on video slides. Perhaps a reasonable compromise.

eg.

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

with:

<!-- 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>

Demo: https://jsfiddle.net/zqhLqfck/

答案 1 :(得分:1)

另一种方法,但更符合您的要求,就是在视频上添加叠加层,只将点击事件传递给视频。

它将叠加层拉伸到视频区域的大小,同时排除底部的视频控制条。

div那个控制栏中添加了类&#39; swiper-no-swiping&#39;停止视频手势被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/

答案 2 :(得分:0)

这将只为视频js的控制栏设置无滑动。

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

滑动仍然适用于视频 div。