jQuery自定义滚动条和延迟加载

6
我有一个带有自定义内容滚动条jQuery custom content scroller的容器: 这是代码:
(function($){
    $(window).load(function(){
        $(".content").mCustomScrollbar({
            scrollButtons: { enable: true },
            mouseWheelPixels: 250
        });
    });
})(jQuery);

我想要与Lazy Load一起使用它:

$(function() {
  $("img.lazy").lazyload({
     effect : "fadeIn",
     container: $(".content")
  });
});

我认为它应该使用Scroller页面的回调函数来工作,但我不擅长jquery,所以我的结果没有成功。
当我像下面这样使用我的代码时,它会在页面加载时加载所有图像:
$(function() {
  $("img.lazy").lazyload({
     effect : "fadeIn",
     container: $(".mCSB_container")
  });
});

作者表示可以通过编写一个简单的js函数,在whileScrolling事件上调用它来实现。
谢谢任何帮助。
4个回答

5

你尝试使用container是不起作用的,因为mCustomScrollbar不使用滚动容器,而是在overflow: hidden容器中使用相对定位来实现滚动。我能想到的最简洁的方法是使用自定义[事件来触发懒加载][1]。以下是我为Hasan Gürsoy提供的示例文件所做的方式:

<script>
$(document).ready(function () {
    var filledHeight = 250;
    $(window).load(function () {
        $(".scroll").height($(window).height() - filledHeight);
        $(".scroll").mCustomScrollbar({ scrollButtons: { enable: true },
        mouseWheelPixels: 250,
        callbacks: { whileScrolling: function() {
            var scroller = $(".mCSB_container");
            var scrollerBox = scroller.closest(".mCustomScrollBox");
            $(".scroll img.lazy").filter(function() {
                var $this = $(this);
                if($this.attr("src") == $this.data("src")) return false;
                var scrollerTop = scroller.position().top;
                var scrollerHeight = scrollerBox.height();
                var offset = $this.closest("div").position();
                return (offset.top < scrollerHeight - scrollerTop);
            }).trigger("lazyScroll");
            }}});

        $("img.lazy").lazyload({ event: "lazyScroll" });
    });
});
</script>

我还使用了一个`whileScrolling`回调函数,但只是为了检查哪些`img.lazy`图片是可见的。它们的相对位置与容器的高度减去其CSS `top`属性不大即可。 (假设您总是从上到下滚动;这个设置无法识别因向下滚动太远而不可见的图像。)对于这些图像,函数会触发自定义的`lazyScroll`事件,这是lazyload用于触发加载图像的事件。
请注意,此解决方案尚不太可移植:您必须将查询`.mCSB_container`和`.mCustomScrollBox`替换为获取与当前滚动框相关联的元素的查询,以使该脚本在具有多个`mCustomScrollbar`的情况下工作。在实际应用中,我也会缓存jQuery对象,而不是在每次调用回调时重新创建它们。

谢谢。这是更好的解决方案。 - HasanG

2
我认为作者的意思是在代码中额外加入对whileScrolling事件的钩子,像这样:

(function($){

    $(window).load(function(){

        $("#content_1").mCustomScrollbar({
            scrollButtons:{
                enable:true
            },
            callbacks:{
                whileScrolling:function(){ WhileScrolling(); } 
            }
        });

        function WhileScrolling(){
            $("img.lazy").lazyload();
        }

    });

})(jQuery);

HTML容器如下所示:

<div id="content_1" class="content">
    <p>Lorem ipsum dolor sit amet. Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit.</p>
    <p>
        <img class="lazy img-responsive" data-original="/img/bmw_m1_hood.jpg" width="765" height="574" alt="BMW M1 Hood"><br/>
        <img class="lazy img-responsive" data-original="/img/bmw_m1_side.jpg" width="765" height="574" alt="BMW M1 Side"><br/>
        <img class="lazy img-responsive" data-original="/img/viper_1.jpg" width="765" height="574" alt="Viper 1"><br/>
        <img class="lazy img-responsive" data-original="/img/viper_corner.jpg" width="765" height="574" alt="Viper Corner"><br/>
        <img class="lazy img-responsive" data-original="/img/bmw_m3_gt.jpg" width="765" height="574" alt="BMW M3 GT"><br/>
        <img class="lazy img-responsive" data-original="/img/corvette_pitstop.jpg" width="765" height="574" alt="Corvette Pitstop"><br/> 
    </p>
    <p>Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit. Nullam felis tellus, tristique nec egestas in, luctus sed diam. Suspendisse potenti. </p>
    <p>Consectetur adipiscing elit. Nulla consectetur libero consectetur quam consequat nec tincidunt massa feugiat. Donec egestas mi turpis. Fusce adipiscing dui eu metus gravida vel facilisis ligula iaculis. Cras a rhoncus massa. Donec sed purus eget nunc placerat consequat.</p>
    <p>Cras venenatis condimentum nibh a mollis. Duis id sapien nibh. Vivamus porttitor, felis quis blandit tincidunt, erat magna scelerisque urna, a faucibus erat nisl eget nisl. Aliquam consequat turpis id velit egestas a posuere orci semper. Mauris suscipit erat quis urna adipiscing ultricies. In hac habitasse platea dictumst. Nulla scelerisque lorem quis dui sagittis egestas.</p> 
    <p>Etiam sed massa felis, aliquam pellentesque est.</p>
    <p>the end.</p>
</div>

为了减少滚动时lazyload()的数量,我们可以使用例如mcs.top属性来获取滚动内容的顶部位置(像素):
function WhileScrolling()
{
    // Debug:
    // console.log( 'top: ' + mcs.top );

    // Run lazyload in 10 pixel steps (adjust to your needs) 
    if( 0 == mcs.top % 10 )
    {
        // Run lazyload on the "div#conent_1" box:
        $("#content_1 img.lazy").lazyload();

        // Debug:
        //console.log( 'lazyload - mcs.top: ' + mcs.top );
    }
}

在这里,我们限制了懒加载选择器,这样我们就不必查找整个DOM树中的所有图像。

我注意到在Internet Explorer 11中,mcs.top可以是浮点数,但在Chrome中它总是整数。

因此,我们可以使用Math.floor()对其进行向下取整。

为了进一步减少lazyload调用,我们可以将mcs.top与其先前的值进行比较:

var mcsTopPrev = 0;
var mcsTop = 0;
function WhileScrolling()
{
    // Fix the Chrome vs Internet Explorer difference
    mcsTop = Math.floor( mcs.top );

    // Current vs previous 
    if(  mcsTop != mcsTopPrev )
    {
        // Run lazyload in 10px scrolling steps (adjust to your needs)
        if( 0 == mcsTop % 10 )
        {
            $("#cphContent_lReferences img.lazy").lazyload();
        }
    }
    mcsTopPrev =  mcsTop;
}

它能够工作,但被多次调用并且也修改了已经加载的图像。 - HasanG
可能已经有一个函数来防止懒加载刷新已经加载的图像。我现在正在谷歌搜索它。 - HasanG
更新很有用,但在Firefox中滚动仍然会出现故障。此外,IE11在滚动时意外地无法加载其余的图像。 - HasanG
我发现为什么IE11的行为与Chrome不同,是由于mcs.top的值不同。即使没有whileScrolling()回调函数,jQuery自定义内容滚动条在我的FireFox中表现奇怪。因此,我不确定懒加载调用是否对FireFox中的这些故障负责。 - birgire
不需要多次调用lazyload()。当图像滚动到视图中时,您只需要触发lazyload等待的事件即可。请参见我的其他答案。 - Phillip
显示剩余5条评论

1

我正在使用插件Lazy LoadCustom Content Scroller,并遇到了同样的问题。

对我有效的方法是在mCustomScrollbarwhileScrolling事件中添加回调函数,在其中触发我正在延迟加载的容器的滚动事件:

/* Lazy load images */
$(".blog-items img.lazyload").lazyload({
  effect: "fadeIn",
  effect_speed: 1000,
  skip_invisible: true,
  container: $(".blog-items")
});

/* Custom scrollbar */
$(".blog-items").mCustomScrollbar({
  theme: "rounded-dark",
  callbacks: {
    whileScrolling: function() {
      $(".blog-items").trigger("scroll");
    }
  }
});

我将lazyload属性中的skip_invisible设置为true,希望提高性能。如果遇到问题,请将其设置为false。

我已经尝试解决这个问题快要一周了。最终终于搞定了。非常感谢您的帖子,您让我的一天变得美好 :-) - Peter Karlsson

0

最后,我编写了这个可以从mCustomScrollbar回调中调用的函数:

    function lazyLoad(selector,container) {     

      var $container=$(container);            
      var container_offset=$container.offset();
      container_offset.bottom=container_offset.top+$container.height();

      $(selector,$container).filter(function(index,img){
        if (!img.loaded) {                    
          var img_offset=$(img).offset();     
          img_offset.bottom=img_offset.top+img.height;
          return (img_offset.top<container_offset.bottom && (img_offset.top>0 || img_offset.bottom>0));
        }                                                                                                                                        
      }).trigger('appear');

    }

如果图像大小是恒定的,而图像列表很大,也许值得使用二分法搜索第一张图像,然后使用已知的图像和容器尺寸以及匹配图像的偏移量计算必须触发“出现”事件的索引范围...

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