如何在使用infinitescroll时,只有在所有HTML5视频加载完成后才运行砌体布局?

12

砖石无限滚动追加HTML5视频重叠

我目前正在使用imagesLoaded库,它会检查图像是否加载完成,然后调用masonry

但是,由于这个库不能与HTML5视频标签配合使用,因此视频会重叠在一起。

因此,我将masonry的调用从document.ready改为window.load,并在初始加载时删除对imagesLoaded的调用。具体来说,就是从以下这行代码:

$(document).ready(function(){

    var $container = $('#media');
    // layout Masonry again after all images have loaded
    $container.imagesLoaded( function() {

      $container.masonry({
          "columnWidth": "." + "col-sm-2",
          itemSelector: '.item',
          gutter: 0,
        });
      $('.item').css('opacity', '1.0');
    });

});
至此
$(window).load(function(){
        var $container = $('#media');

          $container.masonry({
              "columnWidth": "." + "col-sm-2",
              itemSelector: '.item',
              gutter: 0,
            });
          $('.item').css('opacity', '1.0');
});

现在,在masonry中的html5视频不会重叠,并且在页面的第一次加载即初始加载时完美呈现, 但是,由于我还使用了infinite-scroll,它会在向下滚动页面时添加更多的图像/视频,因此当新的视频被添加到容器中时它们会重叠,这种行为是由于masonry在所有视频元素被加载之前过早运行造成的,因为imagesloaded无法检查视频加载

这是代码。

$(document).ready(function(){
    var $container = $('#media');
    var no_more_media = "<?= Lang::get('lang.no_more_to_load') ?>";
    var loading_more_media = "<?= Lang::get('lang.loading_more_media') ?>";

    $container.imagesLoaded(function(){
            $container.masonry();
        });

$container.infinitescroll({
        loading: {
            finished: undefined,
            finishedMsg: "<p>" + no_more_media + "</p>",
            img: "data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
            msg: null,
            msgText: "<div class='loading'><i></i><i></i><i></i></div><p>" + loading_more_media + "</p>",
            selector: null,
            speed: 'fast',
            start: undefined,
        },
        navSelector  : "ul.pagination",            
                       // selector for the paged navigation (it will be hidden)
        nextSelector : "ul.pagination a:first",    
                       // selector for the NEXT link (to page 2)
        itemSelector : ".container #media .item",
        animate: false,
        bufferPx: 160,
      },

      function( newElements ) {
         // hide new items while they are loading
        //var $newElems = 
        $.each($(newElements), function(index, value){
            item_click_events($(value));
        });

            $( newElements ).css({ opacity: 0 });

            $(newElements).imagesLoaded(function(){
               var $newElems = $( newElements );
               $newElems.animate({ opacity: 1 });
               $container.masonry( 'appended', $newElems, true);
            }
            );

      });
});

我尝试将上面的代码中的 document.ready 改为 window.load,并完全删除运行 imagesloaded,但与 infinitescroll 一起使用时仍然无法正常工作。

例如,修改后的代码:

$(window).load(function(){
    var $container = $('#media');
    var no_more_media = "<?= Lang::get('lang.no_more_to_load') ?>";
    var loading_more_media = "<?= Lang::get('lang.loading_more_media') ?>";

            $container.masonry();

    $container.infinitescroll({
        loading: {
            finished: undefined,
            finishedMsg: "<p>" + no_more_media + "</p>",
            img: "data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
            msg: null,
            msgText: "<div class='loading'><i></i><i></i><i></i></div><p>" + loading_more_media + "</p>",
            selector: null,
            speed: 'fast',
            start: undefined,
        },
        navSelector  : "ul.pagination",            
                       // selector for the paged navigation (it will be hidden)
        nextSelector : "ul.pagination a:first",    
                       // selector for the NEXT link (to page 2)
        itemSelector : ".container #media .item",
        animate: false,
        bufferPx: 160,
      },

      function( newElements ) {
         // hide new items while they are loading
        //var $newElems = 
        $.each($(newElements), function(index, value){
            item_click_events($(value));
        });

            $( newElements ).css({ opacity: 0 });

               var $newElems = $( newElements );
               $newElems.animate({ opacity: 1 });
               $container.masonry( 'appended', $newElems, true);

      });
});

还有另一种方法可以解决重叠问题,即指定视频的宽度和高度,但由于它是响应式设计,指定视频的宽度和高度会破坏其响应性。

所以我的问题是, 是否有类似于 imagesloaded 的 js 库,可以确保所有视频都已加载,然后我才能调用 masonry? 或者我如何确保视频在 infinitescroll 上不会发生重叠?


更新 1:

我尝试了许多技术,用于 infinitescroll。

$(newElements).load(function(){
   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);
});

页面滚动后未能加载新内容。

$(window).load(function(){
   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);
});

滚动页面后无法加载新内容。

   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);

视频内容重叠

所以我想到了提前调用 infinite-scroll 并将 container.masonry 延迟 3 秒,目前这个方法可以完美解决问题,但仍在等待更好的解决方案。

例如:

bufferPx: 700,

setTimeout(function(){
       var $newElems = $( newElements );
       $newElems.animate({ opacity: 1 });
       $container.masonry( 'appended', $newElems, true);
}, 3000);

上述代码延迟了3秒后才运行砌体布局。

我试图找到类似于 window.loaddiv,但是没有,所以我的最佳选择是检查所有的videosimages是否加载完成,然后在调用infinite-scroll之后再调用masonry


增加了可工作的演示http://plnkr.co/edit/46YzHBJ7eFAXfsPqZB1q你可以通过点击“run”并向下滚动来查看问题。


添加一个小例子或者代码片段,我(或其他人)会修复它。 - Willem D'Haeseleer
一个fiddle肯定是最好的结果,对于这个问题来说也是最有价值的。添加外部链接通常不被鼓励,因为会出现“链接失效”的情况。但如果你真的无法添加fiddle,那么链接可能还可以。我认为没有反对NSFW链接的政策。 - Willem D'Haeseleer
添加了工作演示 http://plnkr.co/edit/46YzHBJ7eFAXfsPqZB1q - user1642018
1个回答

7

看起来你可以通过等待视频的loadeddata事件来修复它。

基本思路如下:

function waitForvidLoad(vids, callback) {
     /* if no videos i.e. mobile mode only gifs and jpgs then call callback else masonry breaks.*/
        if(vids.length === 0){
            callback();
        }
    var vidsLoaded = 0;
    vids.on('loadeddata', function() {
      vidsLoaded++;
      if (vids.length === vidsLoaded) {
        callback();
      }
    });
  }

.

  var $container = $('#container');
  var vids = $('#container').find('video');
  waitForvidLoad(vids, function() {
    $container.imagesLoaded(function() {
      $container.masonry({
        itemSelector: '.box',
        columnWidth: 100
      });
  });

这里有一个可工作的plunker: http://plnkr.co/edit/jXJ7oFxF3sFWBAJuBqdQ?p=preview


@AMB 你能使用这个来修复你网站上的问题吗? - Willem D'Haeseleer
嗨,还没有呢,我还在尝试各种代码组合,但是都还没有成功。初始加载时没问题,因为我使用了window.load,但是问题出现在第二次加载时。 - user1642018
我尝试了来自 Plunkr 的完全相同的代码,现在瀑布流中有垂直间隙,但不再有视频重叠。 - user1642018
好的,更新,如果我即使用你的代码进行初始加载,那么它会破坏砌体结构,会出现垂直间隙。我仔细检查过,如果不使用你的解决方案,那么砌体结构就正常工作。对于初始加载,有任何特定的原因吗?我会在演示中添加不同尺寸的图像,这样就清楚了是什么导致了砌体结构的破裂。 - user1642018
好的,这里有一个新的 Plunkr,展示了使用相同的旧代码破坏了砌体布局。+解决方案,http://embed.plnkr.co/7Ibw9eCFu0N49HEDWtmv/ - user1642018
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接