HTML5 和 Javascript 仅在可见时播放视频

问题描述 投票:0回答:14

我有兴趣设置一个包含多个视频剪辑的 HTML 页面,以便每个视频剪辑仅在可见时播放,然后在看不见时暂停。

我发现了这个很好的例子,说明了如何使用一个剪辑来实现这一点,但我无法修改代码以使用多个剪辑。也许我需要将此代码转换为函数以便于重用?

这是我到目前为止所拥有的(上面链接的 JS Bin 已修改为 2 个剪辑而不是 1 个)。

此代码似乎仅适用于两个剪辑之一。

<!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>
javascript html video html5-video
14个回答
27
投票

使用 isInViewport 插件和 jQuery,这是我的任务代码

$('video').each(function(){
    if ($(this).is(":in-viewport")) {
        $(this)[0].play();
    } else {
        $(this)[0].pause();
    }
})

27
投票

好吧,我想,一定是这样的:

var videos = document.getElementsByTagName("video");

function checkScroll() {
    var fraction = 0.8; // Play when 80% of the player is visible.

    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);

23
投票

以上似乎都不适合我,但我终于找到了一种方法:你需要

visible
插件,以及这里的一小段代码:

$(window).scroll(function() {
    $('video').each(function() {
        if ($(this).visible(true)) {
            $(this)[0].play();
        } else {
            $(this)[0].pause();
        }
    })
});

这将允许任何视频仅在进入视口时播放。将

visible( true )
替换为
visible()
,您可以将其设置为仅当整个视频 DOM 元素位于视口中时才播放。


9
投票

你们都需要与时俱进并使用 IntersectionObserver (以及适当的 polyfill 或 babeifyl)。当页面滚动进入/退出视图时,此脚本将播放/暂停页面上的所有视频。繁荣。

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

来源


7
投票

需要检查视频在滚动过程中是否可见。

 $(window).scroll(function() {
    $('video').each(function(){
        if ($(this).is(":in-viewport")) {
            $(this)[0].play();
        } else {
            $(this)[0].pause();
        }
    })
});

3
投票

使用 jQuery、isInViewport 和 Coffeescript,对我来说完整的解决方案如下所示:

$(window).scroll ->
  $('video:in-viewport').each -> $(@)[0].play()
  $('video:not(:in-viewport)').each -> $(@)[0].pause()

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,因此您可能需要对其进行一些修改才能使您的实现正常工作。


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);
}

2
投票

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);
}, {passive: true});

window.addEventListener("resize", playVisibleVideos);
window.addEventListener("DOMContentLoaded", playVisibleVideos);

setTimeout
的东西可确保当用户滚动时,
playVisibleVideos()
函数的调用频率不会超过每 100 毫秒一次(因此不会导致延迟)。
{passive: true}
确保滚动处理函数不会“阻止”滚动(这可能导致滚动滞后)。

请注意,对于大多数人来说,使用更现代的 IntersectionObserver 方法似乎是比这更好的选择。

    


1
投票

$(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. } }); });



1
投票
IsInView 插件

配合使用的 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


1
投票
没有任何依赖项

,这里是: let video = document.getElementById('video') function playVideoOnScroll () { const threshold = 300 //px above the video to start playing let offset = video.getBoundingClientRect().top if (offset < threshold) { demoVideo.play() } else { demoVideo.pause() } } window.addEventListener('scroll', playVideoOnScroll, false) window.addEventListener('resize', playVideoOnScroll, false)



1
投票
2023

Javascript 中使用 IntersectionObserver: 的工作解决方案 document.addEventListener('DOMContentLoaded', function() { const videos = document.querySelectorAll('video'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.play(); } else { entry.target.pause(); } }); }); videos.forEach(video => { observer.observe(video); }); });



0
投票

$(window).scroll(function () { const viewportBottom = window.scrollY + window.innerHeight; $('video').each(function () { if ($(this).offset().top + $(this).height() < window.scrollY) { $(this)[0].pause(); } else if ($(this).offset().top < viewportBottom) { $(this)[0].play(); } }); });

© www.soinside.com 2019 - 2024. All rights reserved.