web-dev-qa-db-fra.com

HTML5 et Javascript pour lire des vidéos uniquement lorsqu'elles sont visibles

Je souhaite créer une page HTML avec plusieurs clips vidéo de telle sorte que chaque clip vidéo soit lu uniquement lorsqu'il est visible, puis s'arrête lorsqu'il n'est pas visible.

J'ai trouvé ce grand exemple de la façon dont cela peut être implémenté avec un clip, mais je n'ai pas pu modifier le code pour qu'il fonctionne avec plusieurs clips. Peut-être ai-je besoin de convertir ce code en fonction pour une réutilisation facile?

Voici ce que j'ai jusqu'à présent (JS Bin lié ci-dessus modifié pour 2 clips au lieu d'un).

Ce code semble fonctionner pour un seul des deux clips.

<!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>
15
UltrasoundJelly

En utilisant le plugin isInViewport et jQuery , voici mon code pour la tâche

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

OK, je pense que ça doit être quelque chose comme ça:

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

Rien de ce qui précède ne semblait fonctionner pour moi, mais j'ai finalement trouvé un moyen: vous aurez besoin de le plugin visible , et ce petit morceau de code ici:

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

Cela permettra à toute vidéo de jouer uniquement lorsqu'elle entre dans la fenêtre d'affichage. En remplaçant visible( true ) par visible(), vous pouvez le configurer pour qu'il ne soit lu que lorsque tout l'élément DOM vidéo est dans la fenêtre d'affichage.

13
Pierre Olivier Tran

Besoin de vérifier si la vidéo est visible pendant le défilement.

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

Vieille question, mais je voulais juste ajouter mes deux cents, j'ai d'abord commencé avec le code jQuery ci-dessus, mais j'ai rencontré quelques problèmes avec la mise en œuvre. Cette solution devrait fonctionner avec plusieurs vidéos, et empêche également un problème où l'utilisateur interrompt une vidéo et essaie de défiler et elle recommence simplement:

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

J'ai nettoyé quelques trucs, et j'utilise video-js, donc vous devrez peut-être le modifier un peu pour que votre implémentation fonctionne.

2
doveiya

J'ai essayé de nombreuses solutions, la seule qui fonctionne partiellement est celle affichée ci-dessous. Le problème est que le fait d'avoir 3 vidéos sur la page, la seconde et la troisième sont fondamentalement contrôlées par la première.

Donc, ils commencent à jouer lorsque la page est chargée (alors qu'ils sont censés jouer lorsqu'ils sont dans la fenêtre) et ils se mettent en pause lorsque le premier est mis en pause, une suggestion pour que cela fonctionne avec plusieurs vidéos?

Essayé avec getElementById mais n'a pas fonctionné, a également essayé les plugins jquery mais aucun bon résultat.

Ici, vous avez la page www où vous pouvez voir ce qui se passe et tout le code source bien sûr.

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
Me on the web

En utilisant jQuery, isInViewport et Coffeescript, la solution complète pour moi ressemblait à ceci:

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

Au cas où quelqu'un d'autre rencontrerait cette question, je n'ai pas pu utiliser la solution de Saike sur mon WordPress en raison de la façon dont les vidéos ont été automatiquement intégrées (lecteur MediaElement). Cependant, la solution de qwazix a fonctionné avec certains Voici le code jQuery qui fonctionne avec le plugin IsInView Voici mes scripts include (placés à la fin de footer.php dans mon dossier de thème).

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

Et le code jQuery (modifiez 400 à votre convenance)

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

Le seul problème que j'ai avec ce code est qu'il redémarre un clip vidéo en défilement même s'il est interrompu par l'utilisateur. Ce n'était pas un problème révolutionnaire sur mon site. Voici le code en action: ltrasoundoftheweek.com

1
UltrasoundJelly

C'est ainsi que j'ai réussi à lire une vidéo uniquement lorsque l'utilisateur y fait défiler. J'ai utilisé le plugin IsInViewport. J'espère que vous le trouverez utile!

$(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
Leandro Videla