I have 2 videos that work like Instagram reels, when a user clicks the first video it starts playing, but if they scroll to the next video and click to start it the previous video keeps playing. What I would like is only the video in the current view to play and all other videos be paused but cant seem to figure it out. Ideally just autoplay the video in the viewport and auto-pause the rest. I've looked at similar issues on Stack but have had no luck achieving this.
The HTML
<div class="app__videos">
<div class="video">
<video src="video1.mp4" class="video__player"></video>
</div>
<div class="video">
<video src="video2.mp4"></video>
</div>
</div>
The JS
function loadVideos(){
var videos = document.querySelectorAll('video');
for(const video of videos){
// ive tried changing the click function to scroll but didn't work
video.addEventListener('click', function(){
if(video.paused){
video.play();
}else{
video.pause()
}
});
}
}
loadVideos()
** Edit
// Tried adding a scrolling event listener
function loadVideos(){
var videos = document.querySelectorAll('video');
for(const video of videos){
var elem = document.getElementById('app__videos');
elem.addEventListener('scroll', function(){
if(video.paused){
video.play();
}else{
video.pause()
}
});
}
}
loadVideos()
** Edit 2 per Dale, this detects all scrolling, not detecting the bottom of a video
function getScroll(){
var elem = document.getElementById('app__videos');
elem.sections = [...document.querySelectorAll('video')];
elem.lastScrollTop = window.pageYOffset;
elem.addEventListener('scroll', onScroll);
function onScroll() {
const scrollTop = elem.pageYOffset;
const section = elem.sections
.map(section => {
const el = section;
const rect = el.getBoundingClientRect();
return {el, rect};
})
.find(section => section.rect.bottom >= (elem.innerHeight * 0.5));
console.log("bottom of video")
}
}
getScroll()
** Edit 3 , I got it working to stop playing videos on scroll. I still cannot get the next video to start autoplaying without a user click though, If I try to autoplay it plays all videos not the current one in view.
function loadVideos(){
var videos = document.querySelectorAll('video');
for(const video of videos){
let playAfterThisHeight = 500
$('.app__videos').scroll(function() {
if ($('.app__videos').scrollTop()> playAfterThisHeight) {
video.pause()
} else {
}
})
video.addEventListener('click', function(){
if(video.paused){
video.play();
}else{
video.pause()
}
});
}
}
loadVideos()
The CSS with snap-to
*{
margin:0;
box-sizing:border-box;
}
body{
background:black;
color:#fff;
height:100vh;
display:grid;
place-items:center;
}
html{
scroll-snap-type: y mandatory;
}
.app__videos{
position:relative;
height:750px;
background:#fff;
overflow:scroll;
width:100%;
max-width:400px;
scroll-snap-type: y mandatory;
}
.app__videos:: webkit-scrollbar{
display:none;
}
.app__videos{
--ms-overflow-style:none;
scrollbar-width:none;
}
.video{
position:relative;
width:100%;
height:100%;
background:#fff;
scroll-snap-align:start;
}
.video__player{
object-fit:cover;
width:100%;
height:100%;
}
Everything works great if I want the user to click to play and click to pause each video which isn't good obviously as they would have multiple videos playing if they forget to pause. So how can I change the click function to a autoplay and auto-pause based on the user scroll?