我有兴趣设置一个包含多个视频片段的HTML页面,这样每个视频片段只在可见时播放,然后在视野外时暂停。
我发现this great example如何使用一个剪辑实现这一点,但我无法修改代码以使用多个剪辑。也许我需要将此代码转换为一个易于重用的函数?
这是我到目前为止(JS Bin上面链接修改为2个剪辑而不是一个)。
此代码似乎仅适用于两个剪辑中的一个。
<!DOCTYPE html>
<html>
<!-- Created using jsbin.com Source can be edited via http://jsbin.com/ocupor/1/edit
-->
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
<style>
#right {
position: absolute;
top: 2000px;
}
#video1 {
position: absolute;
left: 2000px;
top: 2000px;
}
#video2 {
position: absolute;
left: 2000px;
top: 3000px;
}
</style>
<style id="jsbin-css">
</style>
</head>
#
<body style="width: 4000px; height: 4000px;">
<div id="info"></div>
<div id="down">
scroll down please...
</div>
<div id="right">
scroll right please...
</div>
<video id="video1">
<source src="http://video-js.zencoder.com/oceans-clip.mp4"/>
</video>
<script>
var video = document.getElementById('video1'), fraction = 0.8;
function checkScroll() {
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
checkScroll();
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
</script>
<video id="video2">
<source src="http://video-js.zencoder.com/oceans-clip.mp4"/>
</video>
<script>
var video = document.getElementById('video2'), fraction = 0.8;
function checkScroll() {
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
} checkScroll();
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
</script>
</body>
</html>
答案 0 :(得分:17)
使用isInViewport插件和jQuery,这是我的任务代码
$('video').each(function(){
if ($(this).is(":in-viewport")) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
})
答案 1 :(得分:14)
好吧,我想,它一定是这样的:
var videos = document.getElementsByTagName("video");
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
答案 2 :(得分:12)
上述所有内容似乎都不适用于我,但我终于找到了一种方法:您需要the visible
plugin,而这一小段代码就在这里:
$(window).scroll(function() {
$('video').each(function() {
if ($(this).visible(true)) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
})
});
这将允许任何视频仅在进入视口时播放。将visible( true )
替换为visible()
,您可以将其设置为仅在整个视频DOM元素位于视口中时播放。
答案 3 :(得分:3)
在滚动过程中需要检查视频是否可见。
$(window).scroll(function() {
$('video').each(function(){
if ($(this).is(":in-viewport")) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
})
});
答案 4 :(得分:2)
老问题,但只是想加我的两分钱,我最初开始使用上面的jQuery代码,但遇到了一些实现问题。此解决方案应该可以与多个视频一起使用,还可以防止用户暂停视频并尝试滚动并再次启动的问题:
<script>
var videoList = [];
var scrollPauseList = [];
var clickedPauseList = [];
</script>
<script>
var myScrollFunc = function() {
$(".video-js").each(function(){
var inView = $(this).is(":in-viewport");
var isPaused = $(this)[0].player.paused();
var playerIdx = videoList.indexOf(this.id);
var scrollPaused = scrollPauseList[playerIdx];
var clickPaused = clickedPauseList[playerIdx];
if (inView) {
var hasEnded = $(this)[0].player.ended();
var curTime = $(this)[0].player.currentTime();
var hasStarted = curTime > 0;
if(hasStarted && !hasEnded && !clickPaused)
{
scrollPauseList[playerIdx] = false;
$(this)[0].player.play();
}
} else if(!isPaused) {
scrollPauseList[playerIdx] = true;
$(this)[0].player.pause();
}
});
};
$(window).scroll(myScrollFunc);
</script>
<video
class="video-js" controls></video>
<script>
$(".video-js").each(function(){
videoList[videoList.length] = this.id;
scrollPauseList[scrollPauseList.length] = false;
clickedPauseList[scrollPauseList.length] = false;
});
for(var i = 0; i < videoList.length; i++)
{
var playerID = videoList[i];
var player = videojs(playerID);
player.on('pause', function() {
var pID = videoList.indexOf(this.id());
if(!scrollPauseList[pID])
{
clickedPauseList[pID] = true;
scrollPauseList[pID] = false;
}
else
{
clickedPauseList[pID] = false;
scrollPauseList[pID] = false;
}
});
}
</script>
我已经擦除了一些东西,而且我正在使用video-js,因此您可能需要稍微修改它以使您的实现工作。
答案 5 :(得分:2)
尝试了很多解决方案,唯一一个部分工作的是下面发布的解决方案。问题是在页面上有3个视频,第二个和第三个基本上由第一个视频控制。
所以他们在页面加载时开始播放(当他们应该在视口中播放时),当第一次暂停时,他们会暂停,有关于使用多个视频的任何建议吗?
尝试使用getElementById
但是没有工作,尝试了jquery插件,但没有很好的结果。
这里有www页面,您可以在其中查看发生的情况和所有源代码。
http://185.197.128.183/~monompro/
window.onload = function() {
var videos = document.getElementsByTagName("video"),
fraction = 0.8;
function checkScroll() {
for (var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = video.offsetLeft,
y = video.offsetTop,
w = video.offsetWidth,
h = video.offsetHeight,
r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
}
答案 6 :(得分:1)
如果有其他人遇到这个问题,我无法在我的WordPress网站上使用Saike的解决方案,因为视频是自动嵌入的方式(MediaElement播放器)。但是,qwazix的解决方案有一些修改。以下是与IsInView plugin一起使用的jQuery代码。这是我的包含脚本(放在我的主题文件夹中footer.php
的末尾)。
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="js/isInViewport.min.js" type="text/javascript"></script>
<script src="js/scrollview.min.js" type="text/javascript"></script>
和jQuery代码(根据你的容忍度修改400)
$(function() {
$(window).scroll(function() {
$('.wp-video-shortcode').each(function() {
var str = $(this).attr('id');
var arr = str.split('_');
typecheck = arr[0];
if ($(this).is(":in-viewport( 400 )") && typecheck == "mep") {
mejs.players[$(this).attr('id')].media.play();
} else if (typecheck == "mep") {
mejs.players[$(this).attr('id')].media.pause();
}
});
});
});
我对此代码的唯一问题是即使用户暂停, 也会在滚动时重新启动视频片段。在我的网站上不是一个破坏性的问题。以下是操作中的代码:Ultrasoundoftheweek.com
答案 7 :(得分:1)
使用jQuery,isInViewport和Coffeescript,我的完整解决方案如下所示:
$(window).scroll ->
$('video:in-viewport').each -> $(@)[0].play()
$('video:not(:in-viewport)').each -> $(@)[0].pause()
答案 8 :(得分:1)
这是我在用户滚动视频时设法播放视频的方法。 我使用了IsInViewport插件。 希望你觉得它很有用!
$(window).scroll(function() {
var video = $('.yourvideo');
$(video).each(function(){
if(video.is(':in-viewport')){
video[0].play();
video.removeClass('yourvideo');
//I removed class to stop repeating the action ".play()" when it is scrolled again.
}
});
});
答案 9 :(得分:0)
你们都需要与时俱进,并使用IntersectionObserver(和适当的polyfill)。滚动/滚动视图时,此脚本将播放/暂停页面上的所有视频。
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver%2CIntersectionObserverEntry"></script>
<script>
let video = document.querySelector('video');
let isPaused = false;
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.intersectionRatio!=1 && !video.paused){
video.pause();
isPaused = true;
}
else if(isPaused) {
video.play();
isPaused=false}
});
}, {threshold: 1});
observer.observe(video);
</script>
答案 10 :(得分:0)
如here所述,offsetTop
/ offsetLeft
/等。与较新的getBoundingClientRect
方法相比,这种方法更慢且更容易出错。以下是一些有效的代码,可以播放在视口中甚至部分可见的所有视频:
function playVisibleVideos() {
document.querySelectorAll("video").forEach(video => elementIsVisible(video) ? video.play() : video.pause());
}
function elementIsVisible(el) {
let rect = el.getBoundingClientRect();
return (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
}
let playVisibleVideosTimeout;
window.addEventListener("scroll", () => {
clearTimeout(playVisibleVideosTimeout);
playVisibleVideosTimeout = setTimeout(playVisibleVideos, 100);
});
window.addEventListener("resize", playVisibleVideos);
window.addEventListener("DOMContentLoaded", playVisibleVideos);
setTimeout
的内容可确保在用户滚动时{100}不会被每100毫秒调用一次(因此不会引起延迟)。
请注意,对于大多数人来说,似乎@Tristanisginger's answer使用更现代的playVisibleVideos()
方法可能是比这更好的选择。
答案 11 :(得分:-2)
$('video').each(function(){
if ($(this).is(":in-viewport")) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
})