I'm using Swiper for a simple slideshow with images and videos. This works like a charm. However, because a design requirement is to have a consistent and nice looking player UI, I need to use Video.js as a video player. So I have Swiper as slideshow plugin and Video.js as video plugin. This is working except that there are event conflicts between these two plugins.
Swiper has a mousedown event on its root, while Video.js has a mousedown event too, on the video and its (dynamically created by Video.js) parent container. When dragging the slide (the video) not only Swiper detects that it must swipe, but also Video.js will handle this as click on the video. Therefore if you swipe to a next slide, this always means that the video is played/paused.
Also, when you drag the circle on the timeline Swiper also detects a swipe.
Is there any chance to patch both event listeners to work together? I'm searching a way without patching the libraries itself. Also the patch should not affect the original behavior of the plugins.
Here's the code I'm reffering to. You can also play with 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>
Another approach, but more inline with what you're asking, is to add an overlay over the video and only pass click events through to the video.
It stretches the overlay to the size of the video area whilst excluding the video control bar at the bottom.
In the div
that that is the control bar add the class 'swiper-no-swiping' to stop video gestures from being recognised by Swiper.
Now swiping on the overlay will not cause the video to play or pause, but clicking on it will and gestures for the video control bar will be ignored by Swiper.
Of course the visible CSS and text is just to help illustrate the overlay, and would be removed.
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>
Demo illustrating the basic concept: https://jsfiddle.net/1vqozv25/4/