如何解决 Swiper 和 Video.Js 之间的事件冲突
How to Fix Event Conflicts Between Swiper and Video.Js
我正在使用 Swiper 制作包含图像和视频的简单幻灯片。这就像一个魅力。但是,因为设计要求是要有一个一致且好看的播放器UI,所以我需要使用Video.js作为视频播放器。所以我有 Swiper 作为幻灯片插件和 Video.js 作为视频插件。除了这两个插件 .
之间存在事件 冲突外,这是有效的
Swiper 在其根上有一个 mousedown 事件,而 Video.js 在视频及其(由 Video.js 动态创建的)父容器上也有一个 mousedown 事件。当拖动幻灯片(视频)时,不仅 Swiper 检测到它必须滑动,而且 Video.js 也会将其处理为点击视频。 因此,如果您滑动到下一张幻灯片,这始终意味着视频是 played/paused。
此外,当您在时间轴上拖动圆圈时,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>
您可以将 class 添加到选项 noSwipingClass
以防止 Swiper 处理带有 class 的幻灯片上的事件。现在只有 next/prev 滑动按钮可以在视频幻灯片上使用。也许是一个合理的妥协。
例如。
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>
另一种方法,但更符合您的要求,是在视频上添加叠加层,并且只将点击事件传递给视频。
它将叠加层拉伸到视频区域的大小,同时排除底部的视频控制栏。
在 div
控制栏中添加 class '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/
这样只会为视频js的控制栏设置无滑动
$( ".vjs-control-bar" ).addClass('swiper-no-swiping');
滑动仍然适用于视频 div。
与 Manev 的回答类似,带有选项 noSwipingClass: 'vjs-control-bar'
的 init Swiper 也可以。
var swiper = new Swiper('.swiper-container', {
noSwipingClass: 'vjs-control-bar'
});
我正在使用 Swiper 制作包含图像和视频的简单幻灯片。这就像一个魅力。但是,因为设计要求是要有一个一致且好看的播放器UI,所以我需要使用Video.js作为视频播放器。所以我有 Swiper 作为幻灯片插件和 Video.js 作为视频插件。除了这两个插件 .
之间存在事件 冲突外,这是有效的Swiper 在其根上有一个 mousedown 事件,而 Video.js 在视频及其(由 Video.js 动态创建的)父容器上也有一个 mousedown 事件。当拖动幻灯片(视频)时,不仅 Swiper 检测到它必须滑动,而且 Video.js 也会将其处理为点击视频。 因此,如果您滑动到下一张幻灯片,这始终意味着视频是 played/paused。
此外,当您在时间轴上拖动圆圈时,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>
您可以将 class 添加到选项 noSwipingClass
以防止 Swiper 处理带有 class 的幻灯片上的事件。现在只有 next/prev 滑动按钮可以在视频幻灯片上使用。也许是一个合理的妥协。
例如。
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>
另一种方法,但更符合您的要求,是在视频上添加叠加层,并且只将点击事件传递给视频。
它将叠加层拉伸到视频区域的大小,同时排除底部的视频控制栏。
在 div
控制栏中添加 class '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/
这样只会为视频js的控制栏设置无滑动
$( ".vjs-control-bar" ).addClass('swiper-no-swiping');
滑动仍然适用于视频 div。
与 Manev 的回答类似,带有选项 noSwipingClass: 'vjs-control-bar'
的 init Swiper 也可以。
var swiper = new Swiper('.swiper-container', {
noSwipingClass: 'vjs-control-bar'
});