Image 懒加载原理分析

2012/10/08 domoffsetx

相信喜欢用 jQuery 的童鞋应该多少了解过 jquery.lazyload.js (opens new window) 这个插件,看了下源码,真是相当的牛逼!关于这个插件各个参数的作用这里就不再赘述,Google 一下有一堆的详解。分析下延迟加载的原理:

在页面的 load 没有触发之前,把所有的指定 id 的元素内的 img 放入到 imgs 中,将所有的图片的 src 值放入到一个新建的 srcattr 属性中,把 src 设置为默认的显示图片。

然后,在 document.bodyscroll 事件触发时,循环计算 imgs 中的 img 元素位置是否正好在浏览器显示框范围内,如果是,则将 img 元素的 srcattr 属性的值赋给 src, 这样图片就能显示出来。

下面是简单的实现:

(function($) {
    // $下定义一个自己的命名空间
    $.xy = $.xy || {};

    $.xy.imgLazyLoad = function (options) {
        // 构造最终参数(默认参数设置与自定义参数合并)
        var settings = $.extend({
                lazySrcName : "srcattr", // 存储 img src 的自定义属性名称
                scrollStep: 200 // 滚动步长
            }, options)
            , imgLoadStatus = 0
            , $window = $(window);

        var _lazyLoad = function () {
            // 要延迟加载的img数组。
            var defObj = $('img[' + settings.lazySrcName + ']');

            // 图片加载的范围
            var pageTop = function () {
                return $(window).height() + $(window).scrollTop();
            };

            _imgLoad(defObj, pageTop());

            var scrollCount = 0;
            // 绑定滚动事件。
            $window.bind('scroll', function () {
                // 往回移动就是负数
                var moved = Math.abs($window.scrollTop() - scrollCount);
                // 累计滚动达到一定的值再去加载图片
                if (moved >= settings.scrollStep) {
                    _imgLoad(defObj, pageTop());
                    if (imgLoadStatus == 1) {
                        scrollCount += settings.scrollStep;
                        imgLoadStatus = 0;
                    }
                }
            });
        },
        _imgLoad = function (defObj, pageTop) {
            // 防止页面有新的图片元素
            defObj = $('img[' + settings.lazySrcName + ']');
            defObj.each(function () {
                var srcattr = $(this).attr(settings.lazySrcName);
                if (srcattr) {
                    // var imgTop = _getPosition($(this)[0]).y;
                    var imgTop = $(this).offset().top;
                    // 如果当前图片 的 top 值 在最大加载范围内。
                    if (
                        imgTop <= pageTop
                        // 如果当前图片的底边位置值大于滚动条滚动的距离
                        && (imgTop + $(this).height()) >= $window.scrollTop()
                    ) {
                        // 将 srcattr 的值载入 src,并且移除 srcattr 属性
                        $(this).attr("src", srcattr).removeAttr(settings.lazySrcName);
                    }
                }
            });
            imgLoadStatus = 1;
        };

        _lazyLoad();
    }
})(jQuery);
上次更新: 2024/4/15 02:28:03