HTML5 и Javascript для воспроизведения видео только при видимых

Я заинтересован в настройке HTML-страницы с несколькими видеоклипами, чтобы каждый видеоклип воспроизводился только тогда, когда он виден, а затем приостанавливался, когда его не видно.

Я нашел этот прекрасный пример того, как это можно реализовать с помощью одного клипа, но я не смог изменить код для работы с несколькими клипами. Возможно, мне нужно преобразовать этот код в функцию для удобства повторного использования?

Вот что у меня есть (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>

Ответ 1

Используя плагин isInViewport и jQuery, здесь мой код для задачи

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

Ответ 2

ОК, я думаю, это должно быть примерно так:

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

Ответ 3

Ничто из вышеперечисленного не показалось мне подходящим, но я наконец нашел способ: вам понадобится visible плагин и этот маленький кусочек кода прямо здесь:

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

Это позволит воспроизводить любое видео только тогда, когда оно попадает в область просмотра. Заменив visible( true ) на visible(), вы можете настроить его на воспроизведение, только когда весь элемент DOM видео находится в области просмотра.

Ответ 4

Необходимо проверить, видно ли видео во время прокрутки.

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

Ответ 5

Старый вопрос, но просто хотел добавить мои два цента, я сначала начал с кода 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, поэтому вам может понадобиться немного изменить его, чтобы ваша реализация работала.

Ответ 6

Перепробовал много решений, единственное частично работающее - это то, которое выложено ниже. Проблема в том, что при наличии 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);
}

Ответ 7

В случае, если кто-то еще сталкивается с этим вопросом, мне не удалось использовать решение Saike на моем сайте WordPress из-за того, как видео было встроено в видео (MediaElement player). Однако решение qwazix работало с некоторыми изменениями. Вот код jQuery, который работает с плагин IsInView. Вот мои включенные сценарии (помещенные в конце 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

Ответ 8

Используя jQuery, isInViewport и Coffeescript, полное решение для меня выглядело так:

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

Ответ 9

Вот как мне удалось воспроизвести видео только тогда, когда пользователь прокручивает его. Я использовал плагин 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.
        }
    });
});

Ответ 10

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