js图片延迟加载的实现方法及思路


Posted in Javascript onJuly 22, 2013

大概的实现方式是:
在页面的load没有触发之前,把所有的指定id的元素内的img放入到imgs中,将所有的图片的src值放入到一个新建的_src属性中,把src设置为指定的显示图片。
然后,在document.body的scroll事件触发时,循环计算imgs中的img元素位置是否正好在浏览器显示框范围内,如果是,则将img元素的_src属性的值赋给src,这样图片就能显示出来。
这里比较麻烦地方是,如何计算img的位置,获得元素的相对于页面的绝对位置。通常是用offsetLeft和offsetTop,但这两个属性是元素的offsetParent指向的元素的相对位置, 如果offsetParent所指的元素是设置了浮动的或使用绝对定位,那么offsetLeft来获得绝对位置就不正确呢。
在这里我是将元素的所有父级元素的offsetTop之和来获得文档绝对位置的。

//取元素的页面绝对 X位置
        var getLeft = function(El){
            var left = 0;
            do{
                left += El.offsetLeft;
            }while((El = El.offsetParent).nodeName != 'BODY');
            return left;
        };
        //取元素的页面绝对 Y位置
        var getTop = function(El){
            var top = 0;
            do{
                top += El.offsetTop;
            }while((El = El.offsetParent).nodeName != 'BODY');
            return top;
        };

在设置窗口的scroll事件时,ie使用是document.documentElement,而其他的浏览器都使用document。
 接下来是要获得浏览器显示窗口现对于文档的位置,用了下面的代码来计算
//读取滚动条的位置和浏览器窗口的显示大小
             var top = isGoo ? document.body.scrollTop : document.documentElement.scrollTop,
                 left = isGoo ? document.body.scrollLeft :document.documentElement.scrollLeft,
                 width = document.documentElement.clientWidth,
                 height = document.documentElement.clientHeight;

谷歌浏览器要通过body来获得scrollTop,而其他浏览器通过documentElement。
 最后迭代判断img的位置,并显示图片
//对所有图片进行批量判断是否在浏览器显示区域内
            for(var i=0 ; i < imgs.length; i++){
                var _top = getTop(imgs[i]),_left = getLeft(imgs[i]);
                //判断图片是否在显示区域内
                if( _top >= top &&
                    _left >= left &&
                    _top <= top+height &&
                    _left <= left+width){
                    var _src = imgs[i].getAttribute('_src');
                    //如果图片已经显示,则取消赋值
                    if(imgs[i].src !== _src){
                        imgs[i].src = _src;
                    }
                }
            }

可以运行的代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>js图片延迟加载</title>
</head>
<body>
<table id="out1" style="height:2450px;">
<tr>
<td><img src="https://3water.com/small/2011_4_22/photo163115955184917.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_13/photo163175537548397.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_4_16/photo16314557927776.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_10/photo1631932180569094.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_4_1/photo1630540642223.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_2/photo1638657445827.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_29/photo16384188604.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_29/photo16384188604.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_4_13/photo16311444254618471.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_15/photo16318118126415.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_14/photo16310513957332.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310342238265.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_14/photo163103452142757.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310310447460.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_14/photo163103347259334.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310342238265.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_14/photo163102333593532.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16323618120479.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_14/photo16323942409450.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_15/photo1630653584606.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_12/photo163233846816799.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_13/photo16313216736705.jpg" alt="" /></td>
</tr>
<tr>
<td><img src="https://3water.com/small/2011_3_1/photo16313391752186220.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_1/photo163765186092776.jpg" alt="" /></td>
</tr>
</table>
<table id="out2" style="width:4883px">
<tr>
<td><img src="https://3water.com/small/2011_4_22/photo163115955184917.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_13/photo163175537548397.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_4_16/photo16314557927776.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_10/photo1631932180569094.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_4_1/photo1630540642223.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_4_2/photo1638657445827.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_29/photo16384188604.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_29/photo16384188604.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_4_13/photo16311444254618471.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_15/photo16318118126415.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_14/photo16310513957332.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310342238265.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_14/photo163103452142757.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310310447460.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_14/photo163103347259334.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16310342238265.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_14/photo163102333593532.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_14/photo16323618120479.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_14/photo16323942409450.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_15/photo1630653584606.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_12/photo163233846816799.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_13/photo16313216736705.jpg" alt="" /></td>
<td><img src="https://3water.com/small/2011_3_1/photo16313391752186220.jpg" alt="" /> </td>
<td><img src="https://3water.com/small/2011_3_1/photo163765186092776.jpg" alt="" /></td>
</tr>
</table>
</body>
</html>
  <script type="text/javascript">
        function delayload(option){
            //读取参数
            //图片未加载时显示的图片
            var src = option.src ? option.src : '',
            //指定那些id下的img元素使用延迟显示
                id = option.id ? option.id : [];
            //图片列表
            var imgs = [];
            //获得所有的图片元素
            for(var i=0 ; i < id.length ; i++){
                var idbox = document.getElementById(id[i]),_imgs;
                if(idbox && (_imgs = idbox.getElementsByTagName('img'))){
                    for(var t=0 ; t < _imgs.length ; t++){
                        imgs.push(_imgs[t]);
                    }
                }
            }
            //将所有的图片设置为指定的loading图片
            for(var i=0 ; i < imgs.length ; i++){
                //图片本来的图片路径放入_src中
                imgs[i].setAttribute('_src',imgs[i].src);
                imgs[i].src = src;
            }
            //取元素的页面绝对 X位置
            var getLeft = function(El){
                var left = 0;
                do{
                    left += El.offsetLeft;
                }while((El = El.offsetParent).nodeName != 'BODY');
                return left;
            };
            //取元素的页面绝对 Y位置
            var getTop = function(El){
                var top = 0;
                do{
                    top += El.offsetTop;
                }while((El = El.offsetParent).nodeName != 'BODY');
                return top;
            };
            //是否为ie,并读出ie版本
            var isIE = !!navigator.userAgent.match(/MSIE\b\s*([0-9]\.[0-9]);/img);
            isIE && (isIE = RegExp.$1);
            //是否为chrome
            var isGoo = !!navigator.userAgent.match(/AppleWebKit\b/img);
            //获得可以触发scroll事件的对象
            var box = isIE ? document.documentElement : document;
            //body元素的scroll事件
            var onscroll = box.onscroll = function(){
                //读取滚动条的位置和浏览器窗口的显示大小
                var top = isGoo ? document.body.scrollTop : document.documentElement.scrollTop,
                    left = isGoo ? document.body.scrollLeft :document.documentElement.scrollLeft,
                    width = document.documentElement.clientWidth,
                    height = document.documentElement.clientHeight;
                //对所有图片进行批量判断是否在浏览器显示区域内
                for(var i=0 ; i < imgs.length; i++){
                    var _top = getTop(imgs[i]),_left = getLeft(imgs[i]);
                    //判断图片是否在显示区域内
                    if( _top >= top &&
                        _left >= left &&
                        _top <= top+height &&
                        _left <= left+width){
                        var _src = imgs[i].getAttribute('_src');
                        //如果图片已经显示,则取消赋值
                        if(imgs[i].src !== _src){
                            imgs[i].src = _src;
                        }
                    }
                }
            };
            var load = new Image();
            load.src = src;
            load.onload = function(){
                onscroll();
            };
        }
        delayload({id:['out1','out2'],src:'//img.jbzj.com/file_images/article/201307/2013072210300234.jpg'});
      </script>
Javascript 相关文章推荐
javascript 函数式编程
Aug 16 Javascript
JS返回上一页实例代码通过图片和按钮分别实现
Aug 16 Javascript
JavaScript实现将文本框的值插入指定位置的方法
Aug 13 Javascript
JavaScript中解决多浏览器兼容性23个问题的快速解决方法
May 19 Javascript
BootStrap下拉菜单和滚动监听插件实现代码
Sep 26 Javascript
BootStrap按钮标签及基本样式
Nov 23 Javascript
Node接收电子邮件的实例代码
Jul 21 Javascript
vue2.0模拟锚点的实例
Mar 14 Javascript
如何更好的编写js async函数
May 13 Javascript
基于vue和react的spa进行按需加载的实现方法
Sep 29 Javascript
js实现图片局部放大效果详解
Mar 18 Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
Apr 28 Javascript
js添加table的行和列 具体实现方法
Jul 22 #Javascript
JS中eval函数的使用示例
Jul 21 #Javascript
JS中prototype关键字的功能介绍及使用示例
Jul 21 #Javascript
原生JS实现表单checkbook获取已选择的值
Jul 21 #Javascript
jquery animate实现鼠标放上去显示离开隐藏效果
Jul 21 #Javascript
jquery封装的对话框简单实现
Jul 21 #Javascript
jquery触发a标签跳转事件示例代码
Jul 21 #Javascript
You might like
php mssql 分页SQL语句优化 持续影响
2009/04/26 PHP
解析PHP中empty is_null和isset的测试
2013/06/29 PHP
PHP使用CURL获取302跳转后的地址实例
2014/05/04 PHP
基于递归实现的php树形菜单代码
2014/11/19 PHP
PHP调试的强悍利器之PHPDBG
2016/02/22 PHP
利用ASP发送和接收XML数据的处理方法与代码
2007/11/13 Javascript
JavaScript 获取用户客户端操作系统版本
2009/08/25 Javascript
javascript 操作cookies及正确使用cookies的属性
2009/10/15 Javascript
JS实现随机化快速排序的实例代码
2013/08/01 Javascript
js data日期初始化的5种方法
2013/12/29 Javascript
详解Javascript模板引擎mustache.js
2016/01/20 Javascript
jquery插件Jplayer使用方法简析
2016/04/22 Javascript
浅谈js基本数据类型和typeof
2016/08/09 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
JQueryMiniUI按照时间进行查询的实现方法
2017/06/07 jQuery
详解ES6系列之私有变量的实现
2018/11/21 Javascript
element的el-table中记录滚动条位置的示例代码
2019/11/06 Javascript
Vue实现验证码功能
2019/12/03 Javascript
JS实现放烟花效果
2020/03/10 Javascript
复制粘贴功能的Python程序
2008/04/04 Python
Python程序语言快速上手教程
2012/07/18 Python
盘点提高 Python 代码效率的方法
2014/07/03 Python
在Django的上下文中设置变量的方法
2015/07/20 Python
Python基于win32ui模块创建弹出式菜单示例
2018/05/09 Python
对python中Librosa的mfcc步骤详解
2019/01/09 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
python检查目录文件权限并修改目录文件权限的操作
2020/03/11 Python
python批量合成bilibili的m4s缓存文件为MP4格式 ver2.5
2020/12/01 Python
html5仿支付宝密码框的实现代码
2017/09/06 HTML / CSS
什么是反射
2012/03/17 面试题
四年大学生活的个人自我评价
2013/12/11 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
小学生家长寄语
2014/04/02 职场文书
党员教师个人对照检查材料(群众路线)
2014/09/26 职场文书
2015年秋季新学期寄语
2015/03/25 职场文书
入党转正介绍人意见
2015/06/03 职场文书