手写图片懒加载js

图片的按需加载——图片懒加载

按需加载图片,就是让图片默认开始不加载,而且在接近可视区域范围时,再进行加载。也称之为懒惰加载。大家都知道,图片一下子全部都加载,请求的次数将会增加,势必影响性能。

先来看下懒惰加载的实现原理。它的触发动作是:当滚动条拉动到某个位置时,即将进入可视范围的图片需要加载。实现的过程分为下面几个步骤:

生成<img data-src="http://tid.tenpay.com/”url”>标签时,用data-src来保存图片地址;
记录的图片data-src都保存到数组里;
对滚动条进行事件绑定,假设绑定的函数为function lazyload(){};
在函数lazyload中,按照下面思路实现:计算图片的Y坐标,并计算可视区域的高度height,当Y小于等于(height+ scrollTop)时,图片的src的值用data-src的来替换,从而来实现图片的按需加载;
代码实例:

 <!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>图片按需加载</title>
</head>

<body>
    <style>
        li {
            float: left;
            width: 200px;
        }
    </style>
    <div style="widh:100%;height:1200px;border:1px solid #000">这里是空白的内容,高度为900像素,目的是方便出现滚动条</div>
    <ul style="width:600px;">
        <li> <img width="158" height="158" data-src="https://t7.baidu.com/it/u=3406125714,2513313326&fm=193&f=GIF" />
        </li>
        <li> <img width="158" height="158" data-src="https://img2.baidu.com/it/u=1788503664,1043895900&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500" /> </li>
        <li> <img width="158" height="158" data-src="https://img0.baidu.com/it/u=3792115810,1999741661&fm=26&fmt=auto" /> </li>
        <li> <img width="158" height="158" data-src="https://img0.baidu.com/it/u=3792115810,1999741661&fm=26&fmt=auto" /> </li>
        <li> <img width="158" height="158" data-src="http://www.mjjq.com/blog/photos/Image/mjjq-photos-903.jpg" /> </li>
        <li> <img width="158" height="158" data-src="http://c.cncnimg.cn/000/954/1416_2_b.jpg" /> </li>
        <li> <img width="158" height="158" data-src="https://img0.baidu.com/it/u=1721391133,702358773&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=625" /> </li>
        <li> <img width="158" height="158" data-src="http://www.mjjq.com/pic/20070530/20070530043314558.jpg" /> </li>
    </ul>
    <script>
        var API = {
            /**
             * 兼容Mozilla(attachEvent)和IE(addEventListener)的on事件
             * @param {String} element DOM对象 例如:window,li等
             * @param {String} type on事件类型,例如:onclick,onscroll等
             * @param {Function} handler 回调事件
             */
            on: function (element, type, handler) {
                return element.addEventListener ? element.addEventListener(type, handler, false) : element
                    .attachEvent('on' + type, handler)
            },
            /**
             * 为对象绑定事件
             * @param {Object} object 对象
             * @param {Function} handler 回调事件
             */
            bind: function (object, handler) {
                return function () {
                    return handler.apply(object, arguments)
                }
            },
            /**
             * 元素在页面中X轴的位置
             * @param {String} element DOM对象 例如:window,li等
             */
            pageX: function (El) {
                var left = 0;
                do {
                    left += El.offsetLeft;

                } while (El.offsetParent && (El = El.offsetParent).nodeName.toUpperCase() != 'BODY');
                return left;

            },
            /**
             * 元素在页面中Y轴的位置
             * @param {String} element DOM对象 例如:window,li等
             */
            pageY: function (El) {
                var top = 0;
                do {
                    top += El.offsetTop;

                } while (El.offsetParent && (El = El.offsetParent).nodeName.toUpperCase() != 'BODY');
                return top;

            },
            /**
             * 判断图片是否已加载
             * @param {String} element DOM对象 例如:window,li等
             * @param {String} className 样式名称
             * @return {Boolean} 布尔值
             */
            hasClass: function (element, className) {
                return new RegExp('(^|\\s)' + className + '(\\s|$)').test(element.className)
            },
            /**
             * 获取或者设置当前元素的属性值
             * @param {String} element DOM对象 例如:window,li等
             * @param {String} attr 属性
             * @param {String} (value) 属性的值,此参数如果没有那么就是获取属性值,此参数如果存在那么就是设置属性值
             */
            attr: function (element, attr, value) {
                if (arguments.length == 2) {
                    return element.attributes[attr] ? element.attributes[attr].nodeValue : undefined
                } else if (arguments.length == 3) {
                    element.setAttribute(attr, value)
                }
            }
        };

        /**
         * 按需加载
         * @param {String} obj 图片区域元素ID
         */
        function lazyload(obj) {
            this.lazy = typeof obj === 'string' ? document.getElementById(obj) : document.getElementsByTagName('body')[
                0];
            this.aImg = this.lazy.getElementsByTagName('img');
            this.fnLoad = API.bind(this, this.load);
            this.load();
            API.on(window, 'scroll', this.fnLoad);
            API.on(window, 'resize', this.fnLoad);

        }
        lazyload.prototype = {

            /**
             * 执行按需加载图片,并将已加载的图片标记为已加载
             * @return 无
             */
            load: function () {
                var iScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                // 屏幕上边缘
                var iClientHeight = document.documentElement.clientHeight + iScrollTop;
                // 屏幕下边缘
                var i = 0;
                var aParent = [];
                var oParent = null;
                var iTop = 0;
                var iBottom = 0;
                var aNotLoaded = this.loaded(0);
                if (this.loaded(1).length != this.aImg.length) {
                    var notLoadedLen = aNotLoaded.length;
                    for (i = 0; i < notLoadedLen; i++) {
                        iTop = API.pageY(aNotLoaded[i]) - 200;
                        iBottom = API.pageY(aNotLoaded[i]) + aNotLoaded[i].offsetHeight + 200;
                        var isTopArea = (iTop > iScrollTop && iTop < iClientHeight) ? true : false;
                        var isBottomArea = (iBottom > iScrollTop && iBottom < iClientHeight) ? true : false;
                        if (isTopArea || isBottomArea) {
                            // 把预存在自定义属性中的真实图片地址赋给src
                            aNotLoaded[i].src = API.attr(aNotLoaded[i], 'data-src') || aNotLoaded[i].src;
                            if (!API.hasClass(aNotLoaded[i], 'loaded')) {
                                if ('' != aNotLoaded[i].className) {
                                    aNotLoaded[i].className = aNotLoaded[i].className.concat(" loaded");

                                } else {
                                    aNotLoaded[i].className = 'loaded';

                                }
                            }
                        }
                    }
                }
            },

            /**
             * 已加载或者未加载的图片数组
             * @param {Number} status 图片是否已加载的状态,0代表未加载,1代表已加载
             * @return Array 返回已加载或者未加载的图片数组
             */
            loaded: function (status) {
                var array = [];
                var i = 0;
                for (i = 0; i < this.aImg.length; i++) {
                    var hasClass = API.hasClass(this.aImg[i], 'loaded');
                    if (!status) {
                        if (!hasClass)
                            array.push(this.aImg[i])
                    }
                    if (status) {
                        if (hasClass)
                            array.push(this.aImg[i])
                    }
                }
                return array;
            }
        };
        // 按需加载初始化
        API.on(window, 'load', function () {
            new lazyload()
        });
    </script>
</body>

</html>

参考文章:https://www.cnblogs.com/mamimi/p/7646358.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值