zoukankan      html  css  js  c++  java
  • js图片延迟加载

    http://www.qiqiboy.com/2011/04/12/javascript-and-images-lazyload.html

    lazyload可以用于很多场合,如JS、css的按需加载;对于页面上很多大图片的网站来说,图片的延迟加载,可以很好的节约页面大小,减少页面与服务器的资源交互,减少用户的等待时间等。所以使用的人越来越多了。

    刚不久前做一个业务时,碰到了此类需求。不同的是,这个网站上没有引入jQuery,所以不能拿别人开发的jQuery lazyload插件来开发了。遂只好自己来写代码了,此文贴出代码,仅作参考交流。代码基本上实现了图片lazyload的需求,不过还有一些问题,如果你对代码有改进建议和意见,欢迎留言告知,先谢!

    可以先看demo,再看代码。

    var addListener=function(e, n, o, u){
        if(e.addEventListener) {
            e.addEventListener(n, o, u);
            return true;
        } else if(e.attachEvent) {
            e['e' + n + o] = o;
            e[n + o] = function() {
                e['e' + n + o](window.event);
            };
            e.attachEvent('on' + n, e[n + o]);
            return true;
        }
        return false;
    },
    getObjPoint=function(o){
        var x=y=0;
        do {
            x += o.offsetLeft || 0;
            y += o.offsetTop  || 0;
            o = o.offsetParent;
        } while (o);
        return {'x':x,'y':y};
    },
    IE=function(){
        if(/msie (d+.d)/i.test(navigator.userAgent)){
            return document.documentMode || parseFloat(RegExp.$1);
        }
        return 0;
    }
    //上面是一些功能函数的封装,下面是lazyload部分
    var lazyload=function(img){
            if(img.complete||img.readyState&&(
                img.readyState=='loaded'||img.readyState=='complete')
                ){//图片已经下载或者缓存就不用继续了
                return false;
            }
            img.setAttribute('_src',img.src);
            img.src='images/nothing.gif';
            //如果不想显示占位loading图片,也可以移除src:img.removeAttribute('src'); 
            //貌似移除src在webkit核心浏览器(safari & chrome)下并不会阻止浏览器下载图片,所以最好还是使用占位图片方式
            //但是请不要将src设置为空,img.src=""; 貌似某些浏览器下还会下载其他东西(IE?)
            var action=function(img){//响应操作
                if(img.getAttribute('loaded')){//判断是否loaded了
                    clearInterval(img.timer);
                    return;
                }
                var doc=document.documentElement,
                    body=document.body,
                    sy=(doc&&doc.scrollTop || body&&body.scrollTop || 0) - (doc&&doc.clientTop || body&&body.clientTop || 0),
                    np=getObjPoint(img),
                    ny=np.y,
                    wy=doc&&doc.clientHeight || body&&body.clientHeight;
                //console.log(ny+'|'+sy+'|'+wy)
                if(Math.abs(ny-sy)<wy){
                //通过计算比较图片与当前浏览器窗口的位置判断图片是否已进入当前可视区域
                    img.setAttribute('loaded','loaded');//设置loaded属性,标记此img已经开始加载
                    img.src=img.getAttribute('_src');//修正src
                    img.onload=img.onerror=img.onreadystatechange=function(){
                    //IE通过onreadystatechange,其他onload
                        if(img&&img.readyState&&img.readyState!='loaded'&&img.readyState!='complete'){
                            return false;
                        }
                        img.onload = img.onreadystatechange = img.onerror = null;
                        var animat=function(el){//一个简单的fadeIn效果
                            var s=0,
                                timer=setInterval(function(){
                                el.style.opacity=s;
                                el.style.filter=('opacity='+(s*100));
                                s+=0.05;
                                if(s>1)clearInterval(timer);
                            },30)
                        }
                        animat(img);
                    };
                }
            }
            action(img);
            if(IE()&&IE()<9){
            //ie8及以下浏览器通过scroll事件绑定貌似有问题,暂时先用定时器实现
                img.timer=setInterval(function(){action(img)},1000);
            }else{
                addListener(window,'scroll',function(){action(img)},false);
            }
        }

    DEMO

    调用代码,可以遍历需要lazyload的图片,然后循环调用lazyload(img)即可,具体可下载demo查看。

    实现原理是遍历图片,判断图片是否已经加载(readyStatte)或者存在缓存(complete),如果还未加载,那么就将图片的src设置成占位图片,然后绑定事件。如果检测到图片已经进入可视区域,那么就将src再设置过来。

    有一些疑问:

    第一,IE下的绑定scroll事件,貌似不能多绑定,只能绑定一个,类似于使用window.onscroll了,原因不明。还未深究,暂时用setInterval替代。

    第二,浏览器对图片的下载加载方式。如果图片正在下载,然后将其src设置为另外一个,那么之前的图片是会立即被abort吗?所有浏览器都是这样的?如果将src设置为空(img.src=”),那么之前的图片会被abort停止加载吗?所有浏览器都这样?移除src(removeAttibute(‘src’))呢?

    如果有人有相关资料,欢迎提供。

    2011.04.12 16:20 更新: 实践证明,我上面疑问的答案是 否,也就是无论你移除src或者重设src,都不能阻止浏览器(chrome、ff>4?)下载之前的图片。所以JS版的lazyload是无意义的。只有前后端配合(页面输出前就将img的src设置为占位图),才能真正lazyload。

    所以大家不要再使用那个神马jquery lazyload了,毫无意义。本文代码也毫无意义。唯一的亮点,大概就是图片加载时的fadeIn效果有一些迷人吧。。。哈哈

  • 相关阅读:
    将不确定变成确定~LINQ DBML模型可以对应多个数据库吗
    将不确定变成确定~frameset页面不能正确加载
    System.Web.Caching.Cache删除某键后,希望同时触发其它动作(关键时刻,还是事件靠的住)
    Linq实体类的设计(解决了复合查询的问题,同时解决了LINQ上下文缓存问题)
    将不确定变成确定~LINQ查询两种写法,性能没有影响,优化查询应该是“按需查询”
    ASP.NET的内置对象
    Templating with JSF 2.0 Facelets
    IOS设计模式学习(1)设计模式初窥
    20个强大的jQuery翻书插件【 jQuery flipbook】
    linux网络编程之socket(十四):基于UDP协议的网络程序
  • 原文地址:https://www.cnblogs.com/daishuguang/p/3661750.html
Copyright © 2011-2022 走看看