收藏本站腾讯微博新浪微博

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 网站开通淘帖功能 - 蓝色理想插件 论坛内容导读一页看论坛 - 给官方提建议

论坛活动及任务 地图和邮件任务 请多用悬赏提问 热夏来袭,选一款蓝色理想的个性T恤吧!

手机上论坛,使用APP获得更好体验 急需前端攻城狮,获得内部推荐机会 论坛开通淘帖功能,收藏终于可以分类了!

搜索
查看: 5930|回复: 10

[作品展示] [原创]发一个简单的非必须不载入图片技术(仿迅雷首页图片被动加载)

[复制链接]
发表于 2011-5-12 14:09:18 | 显示全部楼层 |阅读模式
本帖最后由 fonqing 于 2012-11-24 08:06 编辑

技术原理简介:
     用户访问页面很多时候,并没有滚动到底部,所以有时候很多图片载入却是浪费了时间
      将需要被动加载的图片的src属性用自定义属性写入HTML,src指向一个1像素宽高的占位图片
      根据滚动条位置和图片坐标计算判断图片是否出现在可视区域内,如果是,那么加载图片
技术的好处:
      1,加快页面载入速度,提高用户体验,首页图片较多的页面尤其明显
      2,节省流量和服务器连接数
浏览器测试:IE6 firefox3.6 Firefox4.0 chrome opera 11.10 测试通过,有任何BUG,欢迎大家告诉我
效果:

 提示:您可以先修改部分代码再运行


  1. /**
  2. * Javascript Image Delay load
  3. *
  4. * Javascript实现的页面图片被动加载类,在使用前用1像素图像进行占位
  5. * 并给img tag 添加 自定义bigsrc属性 ,当有图片进入可视区域内时,载入图片
  6. * 提高页面载入速度,节省不必要的流量和连接数
  7. *
  8. * @author Eric,<wangyinglei@yeah.net>,QQ:31301678
  9. * @copyright Aimosoft Studio  2010
  10. * @TODO        x轴滚动加载功能未被实现
  11. */

  12. //闭包防止变量冲突
  13. (function(){

  14.         //预定义变量,减小代码体积
  15.         var _ = document,
  16.                 A = _.compatMode,
  17.                 B = _.body,
  18.                 C = _.documentElement;

  19.         //Constructor
  20.         function AimoLoad(e){

  21.                 //要处理的包含延迟加载图片的容器
  22.                 this.area = e ?  this.get(e) : _;

  23.                 //需要延迟加载的所有图片对象
  24.                 this.imgs = [];

  25.                 //执行判断 条件成立 载入图片
  26.                 this.run();
  27.         }
  28.         //扩展原型链(注册类其他方法)
  29.         AimoLoad.prototype = {

  30.                 //获取DOM元素,仅支持ID
  31.                 'get' : function(e){
  32.                         return typeof(e)=='string' ? _.getElementById(e) : e;
  33.                 },

  34.                 //获取所有需要被动载入的图片集合
  35.                 'getImages' : function(){
  36.                         var i = 0,
  37.                                 imgs = this.area.getElementsByTagName('img'),
  38.                                 l = imgs.length;
  39.                         for ( ; i < l; i++) {
  40.                                 //过滤带有bigsrc属性的所有图片
  41.                                 if(imgs[i].getAttribute('bigsrc')){
  42.                                         this.imgs.push(imgs[i]);
  43.                                 }
  44.                         }
  45.                 },
  46.                
  47.                 //获取元素位置坐标
  48.                 'getPosition' : function(el){
  49.                         var x = 0, y = 0;;
  50.                         if (el.getBoundingClientRect) {
  51.                                 var box = el.getBoundingClientRect(),
  52.                                         el = (A != "CSS1Compat") ?
  53.                                         _.body : C;
  54.                                 x = box.left + el.scrollLeft - el.clientLeft;
  55.                                 y = box.top + el.scrollTop - el.clientTop;
  56.                         } else {
  57.                                 x = el.offsetLeft;
  58.                                 y = el.offsetTop;
  59.                                 var parent = el.offsetParent;
  60.                                 while (parent) {
  61.                                         x += parent.offsetLeft;
  62.                                         y += parent.offsetTop;
  63.                                         parent = parent.offsetParent;
  64.                                 }
  65.                         }
  66.                         return {'x' : x, 'y' : y};
  67.                 },
  68.                
  69.                 //封装判断变量是否定义
  70.                 'defined' : function(o){
  71.                         return (typeof(o)!="undefined");
  72.                 },
  73.                
  74.                 //封装合法化Int变量
  75.                 'zeroFix' : function(n){
  76.                         return (!this.defined(n) || isNaN(n))? 0 : n;
  77.                 },

  78.                 //获取可视部分高度
  79.                 'getVisibileHeight' : function(){
  80.                         var cm = C && (!A || A=="CSS1Compat");
  81.                         if (!window.opera && cm) {
  82.                                 return C.clientHeight;
  83.                         }else if (A && !window.opera && B) {
  84.                                 return B.clientHeight;
  85.                         }
  86.                         return this.zeroFix(self.innerHeight);
  87.                 },

  88.                 //获取垂直滚动条位置
  89.                 'getScrollTop' : function(){
  90.                         if (C && this.defined(C.scrollTop) && C.scrollTop>0) {
  91.                                 return C.scrollTop;
  92.                         }
  93.                         if (B && this.defined(B.scrollTop)) {
  94.                                 return B.scrollTop;
  95.                         }
  96.                         return 0;
  97.                 },
  98.                
  99.                 //执行主函数
  100.                 'run' : function(){

  101.                         //获取其他脚本注册到window上的onscroll和onresize事件,避免冲突
  102.                         var _resize = window.onresize || function(){},
  103.                                 _scroll = window.onscroll || function(){},

  104.                                 //引用自身,另存this指向
  105.                                 _self = this,

  106.                                 //定义注册函数
  107.                                 delayLoad = function(){

  108.                                         //清空前一次获取的所有图片
  109.                                         _self.imgs = [];

  110.                                         //获取当前未载入的图片
  111.                                         _self.getImages();

  112.                                         //如果已经没有被动载入的图片了,那么释放注册的事件,提高性能,节省内存
  113.                                         if(_self.imgs.length==0){
  114.                                                 window.onscroll = function(){
  115.                                                         _scroll();
  116.                                                 };
  117.                                                 window.onresize = function(){
  118.                                                         _resize();
  119.                                                 };
  120.                                                 //alert('清除事件');
  121.                                                 return;
  122.                                         }

  123.                                         var i = 0,
  124.                                                 m = _self.imgs,
  125.                                                 l = _self.imgs.length,
  126.                                                 y = _self.getVisibileHeight(),
  127.                                                 t = _self.getScrollTop();

  128.                                         //遍历所有需要被动载入的图片
  129.                                         for( ; i < l; i++){

  130.                                                 //闭包保证i变量
  131.                                                 (function(i){
  132.                                                        
  133.                                                         //获取每个图像对象的坐标
  134.                                                         var pos = _self.getPosition(m[i]);

  135.                                                         //如果图片出现在可视区域内
  136.                                                         if(t + y > pos.y){
  137.                                                                 //读取bigsrc属性,替换当前src属性
  138.                                                                 m[i].setAttribute('src', m[i].getAttribute('bigsrc'));
  139.                                                                 //删除bigsrc属性,提高性能
  140.                                                                 m[i].removeAttribute('bigsrc');
  141.                                                         }

  142.                                                 })(i);//闭包结束
  143.                                         }//循环结束
  144.                                 };//定义注册函数结束
  145.                        
  146.                         //注册函数到window scroll事件
  147.                         window.onscroll = function(){
  148.                                 _scroll();//执行其他脚本注册到当前事件的函数
  149.                                 delayLoad();
  150.                         };

  151.                         //注册函数到window resize事件
  152.                         window.onresize = function(){
  153.                                 _resize();//执行其他脚本注册到当前事件的函数
  154.                                 delayLoad();
  155.                         };
  156.                 }
  157.         }

  158.         //暴露接口到外部,以便调用
  159.         window.AimoLoad = AimoLoad;
  160. })();
复制代码
[[i] 本帖最后由 fonqing 于 2011-5-12 14:39 编辑 ]

评分

参与人数 1威望 +1 收起 理由
faeng220 + 1 谢谢分享

查看全部评分

发表于 2011-5-12 15:04:07 | 显示全部楼层
楼主,你玩得太高深了,没有怎么看懂。我独自揣测了一下楼主的意思。大概是这样的:在一个DIV中,有一个500页的图片,一次全部加载肯定浪费效率,而且会死机。楼主是想,拖动滚动条,只显示可见区域内的图片。
对于这个问题,我曾是这样解决的(据说,GOOGLE图书也是这样做的):
var timer=null;
DIV.onscroll = function(){
    if(timer) clearTimeout(timer);
    timer = setTimeout(function(){load()},500);
}

这里主要实现load()函数,让其根据DIV.scrollTop计算出,当前可视区域内应该显示的图片就可以了。

这里需要显示的图片应该按照顺序编号,而且每张图片的高度需要一致,否则处理起来就太麻烦了。

上述这个方法适合做整本书籍的阅览。楼主的功能更强大。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-5-12 15:14:39 | 显示全部楼层
嗯 原理是一样的!
也不是玩的太高深,主要是想把代码写的清晰一点,另外考虑了好多问题!
主要解决的是:高度比较大的页面,而且带有比较多图片的情况下,有时候用户进入首页,并没有拉动滚动条就 点击 导航去别的页面了,所有下载了的不但浪费了,而且会拖慢页面载入速度!
回复 支持 反对

使用道具 举报

发表于 2011-5-12 16:18:41 | 显示全部楼层
很强悍啊。。虽然看不懂。
记得另外一个版主cloudgamer也写过一个吧。。
和这个是一样的吗?http://bbs.blueidea.com/viewthread.php?tid=2971273&highlight=

现在我用jq的lazyload插件。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-5-12 20:20:30 | 显示全部楼层
原帖由 [i]wangsdong 于 2011-5-12 16:18 发表
很强悍啊。。虽然看不懂。
记得另外一个版主cloudgamer也写过一个吧。。
和这个是一样的吗?http://bbs.blueidea.com/viewthread.php?tid=2971273&highlight=

现在我用jq的lazyload插件。

嗯,这个我也膜拜过,略有不同!
我的脚本是针对整个窗口为容器的
版主那个是 针对滚动DIV的,技术上要比我的复杂很多!

我的简单和简陋点。去掉注释,稍微压缩下1.72kb 左右,不需要加载其他JS库!

[[i] 本帖最后由 fonqing 于 2011-5-12 20:34 编辑 ]
回复 支持 反对

使用道具 举报

发表于 2011-5-13 08:36:33 | 显示全部楼层
哈哈 其实就是一个jquery插件的功能 lazyload 功能很强大  http://www.wufangbo.com/
回复 支持 反对

使用道具 举报

发表于 2011-5-13 14:35:11 | 显示全部楼层
很早就看美空在使用了,这个网站的客户体验做的很不错,有很多值得借鉴的地方。
比如这个专辑,图片很多,你不往下啦就不会加载。
http://www.moko.cc/post/laomai/471763.html
回复 支持 反对

使用道具 举报

发表于 2011-5-13 15:38:32 | 显示全部楼层
这个还是学习一下哈

短篇小说
回复 支持 反对

使用道具 举报

发表于 2011-5-13 21:23:16 | 显示全部楼层
很好,很实用,值得细看
回复 支持 反对

使用道具 举报

发表于 2011-5-13 23:37:40 | 显示全部楼层
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>AimoLoad Test</title>
</head>
<body>
<script type="text/javascript">
/**
* Javascript Image Delay load
*
* Javascript实现的页面图片被动加载类,在使用前用1像素图像进行占位
* 并给img tag 添加 自定义bigsrc属性 ,当有图片进入可视区域内时,载入图片
* 提高页面载入速度,节省不必要的流量和连接数
*
* @author Eric,<wangyinglei@yeah.net>,QQ:31301678
* @copyright Quanying Network Inc. 2010
* @TODO        x轴滚动加载功能未被实现
*/
//闭包防止变量冲突
(function(){
        //预定义变量,减小代码体积
        var _ = document,
                A = _.compatMode,
                B = _.body,
                C = _.documentElement;
        //Constructor
        function AimoLoad(e){
                //要处理的包含延迟加载图片的容器
                this.area = e ?  this.get(e) : _;
                //需要延迟加载的所有图片对象
                this.imgs = [];
                //执行判断 条件成立 载入图片
                this.run();
        }
        //扩展原型链(注册类其他方法)
        AimoLoad.prototype = {
                //获取DOM元素,仅支持ID
                'get' : function(e){
                        return typeof(e)=='string' ? _.getElementById(e) : e;
                },
                //获取所有需要被动载入的图片集合
                'getImages' : function(){
                        var i = 0,
                                imgs = this.area.getElementsByTagName('img'),
                                l = imgs.length;
                        for ( ; i < l; i++) {
                                //过滤带有bigsrc属性的所有图片
                                if(imgs[i].getAttribute('bigsrc')){
                                        this.imgs.push(imgs[i]);
                                }
                        }
                },
               
                //获取元素位置坐标
                'getPosition' : function(el){
                        var x = 0, y = 0;;
                        if (el.getBoundingClientRect) {
                                var box = el.getBoundingClientRect(),
                                        el = (A != "CSS1Compat") ?
                                        _.body : C;
                                x = box.left + el.scrollLeft - el.clientLeft;
                                y = box.top + el.scrollTop - el.clientTop;
                        } else {
                                x = el.offsetLeft;
                                y = el.offsetTop;
                                var parent = el.offsetParent;
                                while (parent) {
                                        x += parent.offsetLeft;
                                        y += parent.offsetTop;
                                        parent = parent.offsetParent;
                                }
                        }
                        return {'x' : x, 'y' : y};
                },
               
                //封装判断变量是否定义
                'defined' : function(o){
                        return (typeof(o)!="undefined");
                },
               
                //封装合法化Int变量
                'zeroFix' : function(n){
                        return (!this.defined(n) || isNaN(n))? 0 : n;
                },
                //获取可视部分高度
                'getVisibileHeight' : function(){
                        var cm = C && (!A || A=="CSS1Compat");
                        if (!window.opera && cm) {
                                return C.clientHeight;
                        }else if (A && !window.opera && B) {
                                return B.clientHeight;
                        }
                        return this.zeroFix(self.innerHeight);
                },
                //获取垂直滚动条位置
                'getScrollTop' : function(){
                        if (C && this.defined(C.scrollTop) && C.scrollTop>0) {
                                return C.scrollTop;
                        }
                        if (B && this.defined(B.scrollTop)) {
                                return B.scrollTop;
                        }
                        return 0;
                },
               
                //执行主函数
                'run' : function(){
                        //获取其他脚本注册到window上的onscroll和onresize事件,避免冲突
                        var _resize = window.onresize || function(){},
                                _scroll = window.onscroll || function(){},
                                //引用自身,另存this指向
                                _self = this,
                                //定义注册函数
                                delayLoad = function(){
                                        //清空前一次获取的所有图片
                                        _self.imgs = [];
                                        //获取当前未载入的图片
                                        _self.getImages();
                                        //如果已经没有被动载入的图片了,那么释放注册的事件,提高性能,节省内存
                                        if(_self.imgs.length==0){
                                                window.onscroll = function(){
                                                        _scroll();
                                                };
                                                window.onresize = function(){
                                                        _resize();
                                                };
                                                //alert('清除事件');
                                                return;
                                        }
                                        var i = 0,
                                                m = _self.imgs,
                                                l = _self.imgs.length,
                                                y = _self.getVisibileHeight(),
                                                t = _self.getScrollTop();
                                        //遍历所有需要被动载入的图片
                                        for( ; i < l; i++){
                                                //闭包保证i变量
                                                (function(i){
                                                       
                                                        //获取每个图像对象的坐标
                                                        var pos = _self.getPosition(m[i]);
                                                        //如果图片出现在可视区域内
                                                        if(t + y > pos.y){
                                                                //读取bigsrc属性,替换当前src属性
                                                                m[i].setAttribute('src', m[i].getAttribute('bigsrc'));
                                                                //删除bigsrc属性,提高性能
                                                                m[i].removeAttribute('bigsrc');
                                                        }
                                                })(i);//闭包结束
                                        }//循环结束
                                };//定义注册函数结束
                       
                        //注册函数到window scroll事件
                        window.onscroll = function(){
                                _scroll();//执行其他脚本注册到当前事件的函数
                                delayLoad();
                        };
                        //注册函数到window resize事件
                        window.onresize = function(){
                                _resize();//执行其他脚本注册到当前事件的函数
                                delayLoad();
                        };
                }
        }
        //暴露接口到外部,以便调用
        window.AimoLoad = AimoLoad;
})();
</script>
<div id="df" style="margin-top:1000px">
    <img src="http://bbs.blueidea.com/images/default/frame_on.gif" width="200"  bigsrc="http://static.qgyinglou.com/uploadfile/2011/0122/20110122173202762.jpg" />
    <img src="http://bbs.blueidea.com/images/default/frame_on.gif" width="200"  bigsrc="http://static.qgyinglou.com/uploadfile/2011/0122/20110122172626373.jpg" />
    <div style="height:300px;"></div>
    <img src="http://bbs.blueidea.com/images/default/frame_on.gif" width="200"  bigsrc="http://static.qgyinglou.com/uploadfile/2011/0122/20110122172448368.jpg" />
    <img src="http://bbs.blueidea.com/images/default/frame_on.gif" width="200"  bigsrc="http://static.qgyinglou.com/uploadfile/2011/0122/20110122170855344.jpg" />
</div>
<script type="text/javascript">
new AimoLoad();
</script>
</body>
</html>
回复 支持 反对

使用道具 举报

发表于 2011-5-14 01:08:07 | 显示全部楼层
是不是相当于jquery插件lazyload的js原生版?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|Archiver|手机版|blueidea.com ( 湘ICP备12001430号 )  

GMT+8, 2020-8-7 13:09 , Processed in 0.140270 second(s), 9 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表