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 相关文章推荐
excel操作之Add Data to a Spreadsheet Cell
Jun 12 Javascript
Prototype Hash对象 学习
Jul 19 Javascript
编写自己的jQuery插件简单实现代码
Apr 19 Javascript
JavaScript设计模式之策略模式实例
Oct 10 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
Jun 23 Javascript
最全的Javascript编码规范(推荐)
Jun 22 Javascript
浅谈JS验证表单文本域输入空格的问题
Feb 14 Javascript
json 带斜杠时如何解析的实现
Aug 12 Javascript
js实现登录时记住密码的方法分析
Apr 05 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
Sep 16 Javascript
在Angular项目使用socket.io实现通信的方法
Jan 05 Javascript
详解如何解决使用JSON.stringify时遇到的循环引用问题
Mar 23 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代码包装修正版
2008/03/15 PHP
PHP stream_context_create()作用和用法分析
2011/03/29 PHP
PHP内核介绍及扩展开发指南―基础知识
2011/09/11 PHP
php语言流程控制中的主动与被动
2012/11/05 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(六)
2014/06/23 PHP
php打包网站并在线压缩为zip
2016/02/13 PHP
javascript中关于执行环境的杂谈
2011/08/14 Javascript
JavaScript定义类和对象的方法
2014/11/26 Javascript
简述JavaScript的正则表达式中test()方法的使用
2015/06/16 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
js实现右键自定义菜单
2016/12/03 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
NodeJS加密解密及node-rsa加密解密用法详解
2018/10/12 NodeJs
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
详解Next.js页面渲染的优化方案
2019/01/27 Javascript
100行代码实现vue表单校验功能(小白自编)
2019/11/19 Javascript
vant中的toast层级改变操作
2020/11/04 Javascript
Pyramid将models.py文件的内容分布到多个文件的方法
2013/11/27 Python
python使用win32com库播放mp3文件的方法
2015/05/30 Python
TensorFlow中权重的随机初始化的方法
2018/02/11 Python
python实现文件助手中查看微信撤回消息
2019/04/29 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
2019/10/11 Python
为什么python比较流行
2020/06/19 Python
将不规则的Python多维数组拉平到一维的方法实现
2021/01/11 Python
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
如果一个类实现了多个接口但是这些接口有相同的方法名将会怎样
2013/06/16 面试题
电气工程及自动化专业自荐书范文
2013/12/18 职场文书
户外活动策划方案
2014/03/12 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
结婚通知短信大全
2015/04/17 职场文书
观看焦裕禄观后感
2015/06/09 职场文书
选调生挂职锻炼工作总结
2015/10/23 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
深入浅析Django MTV模式
2021/09/04 Python
Redis基本数据类型String常用操作命令
2022/06/01 Redis