`
pcajax
  • 浏览: 2163168 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

ImagesLazyLoad 图片延迟加载效果

阅读更多

之前在做一个图片浏览效果时,要看后面的小图必须等到前面的加载完,而且大图的位置是在大量的小图后面,导致大图要等到小图都加载完才能显示,为了解决这个问题,就想到了Lazyload效果。
现在很多网站都用了类似的效果,如淘宝、Bing等。
这个图片延迟加载效果是在Lazyload的基础上扩展的,主要扩展了获取img元素,获取src和图片加载的部分。

兼容:ie6/7/8, firefox 3.5.5, opera 10.10, safari 4.0.4, chrome 3.0
其中safari和chrome部分功能不支持。

效果预览

图片延迟加载:共有图片 张,未载入 46张

图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传
图片上传预览
多级联动菜单
浮动定位提示
数据延迟加载
简便文件上传

程序说明

【获取图片】

先定义filter函数作为筛选程序:

代码

var getSrc = opt.getSrc,
    filter = $$F.bind( this._filter, this,
            opt["class"],
            getSrc ? function(img){ return getSrc(img); }
                : function(img){ return img.getAttribute( attribute ) || img.src; },
            opt.holder
        );

然后用这个filter函数筛选出需要的图片集合:

this._elems = $$A.filter(
        opt.images || container.getElementsByTagName("img"), filter
    );

如果要自定义图片集合可以在程序可选参数的images属性来设置,否则自动从容器获取img元素作为图片集合。

这里的filter其实是包装了筛选样式cls、获取src的方法getSrc和占位图holder三个参数的_filter筛选程序。
在_filter程序中,会对图片集合进行筛选和整理。
如果自定义了"class"筛选样式,会自动排除样式不对应的图片:

if ( cls && img.className !== cls ) return false;

再用getSrc获取原图地址,即实际要显示的图片地址。
如果有自定义getSrc会优先使用。
没有的话,再通过保存原图地址的_attribute自定义属性从元素获取。
最后才直接从元素的src属性获取。

接着排除src不存在的:

if ( !src ) return false;

要注意处理原图地址就是元素当前src的情况:

if ( src == img.src ) {
if ( img.complete || $$B.chrome || $$B.safari ) return false;
    img.removeAttribute("src");
}

如果complete为true,说明图片已经载入完成了,可以排除;
如果是chrome或safari,不能取消当前加载,所以也排除掉(具体看图片的HTTP请求部分)。
否则,用removeAttribute移除src属性来取消图片当前的加载。

如果设置了holder占位图,就重新设置图片src:

if ( holder ) { img.src = holder; }

最后把原图地址记录到元素的_attribute自定义属性中:

img.setAttribute( this._attribute, src );

逐个图片元素筛选整理后,就得到要加载的图片集合了。

【图片加载】

ImagesLazyLoad相比LazyLoad,已经实现了_onLoadData加载程序,不需要再自己定义加载。
在_onLoadData程序中,主要是用来显示图片。

先用_hasAttribute方法判断是否有_attribute自定义属性。
在_hasAttribute方法中是这样判断的:

this._hasAttribute = $$B.ie6 || $$B.ie7
? function(img){ return attribute in img; }
    : function(img){ return img.hasAttribute( attribute ); };

由于ie6/7跟其他浏览器对attribute和property的理解不同,所以要分开处理,详细参考这里的attribute/property
为了保证兼容性,程序会优先使用attribute的方式来操作自定义属性。

当img有_attribute自定义属性时,就用getAttribute来获取原图地址,并设置img的src,在用removeAttribute来移除自定义属性。
移除的意义在于,当有多个实例使用同一个元素时,能保证图片加载一次后就不会重复加载,即防止实例间的冲突。

【图片的HTTP请求】

这里说说开发过程中发现的一些关于图片加载的问题。

首先是加载空字符串的问题,如果给img的src设为空字符串的话,可能会得到意料之外的结果。
例如在 http://xxx/test.htm 里面的 <img src=""> 会发生以下情况:
ie 会产生相对地址的请求,即:http://xxx/
Safari/Chrome 会产生当前页面地址的请求,即:http://xxx/test.htm
Opera/Firefox 不会产生请求
详细参考Nicholas C. Zakas的“Empty image src can destroy your site”。
如果不想加载图片,不应该把src设为空值,因为还可能会发出请求,浪费资源。
可以像程序那样,通过removeAttribute来移除就行了。

还有一个问题是在Safari和Chrome,由于webkit内核的bug,正在加载的图片并不能取消加载。
所以程序在取消图片加载的部分,如果是Safari或Chrome会继续加载,不进行延迟。
这个问题最初从lifesinger的datalazyload的说明部分看到的,具体可以自己用Fiddler来测试。

更多相关资料可以参考lifesinger的“图片的HTTP请求”。

【继承结构】

在发布的程序中,这是第一个用了继承的,本人平时也没怎么用到,所以还不成熟,算是试试水吧。
程序用wrapper来做继承,详细参考工具库的说明
先用wrapper给ImagesLazyLoad包装(继承)LazyLoad:

var ImagesLazyLoad = $$.wrapper(function(options) {
    ...
}, LazyLoad);

再用extend扩展prototype,添加子类的方法函数:

$$.extend( ImagesLazyLoad.prototype, {
  ...
});

其中_initialize方法用来设置子类属性,由于覆盖了父类的同名方法,所以要通过LazyLoad.prototype._initialize来调用,还要注意用call来修正this。

还有_setOptions方法用来设置子类的可选属性:

return LazyLoad.prototype._setOptions.call(this, $$.extend({
    ...
}, $$.extend( options, {
    onLoadData:    this._onLoadData
})));

子类的_setOptions方法也覆盖了父类的方法,解决方法同_initialize。
其中第一个参数是子类的可选属性,第二个参数是子类定义的属性,即不再是可选而是由程序来定义的属性。

总体来说,这是个简陋的继承,等以后积累了一定经验再来扩展吧。

使用技巧

【设置src】

有几个方法可以设置原图地址:
1,正常设置src:渐进增强,不支持js时也能显示,但chrome和safari有bug,不支持这种方式;
2,把原图地址设置到自定义属性中:所有浏览器都兼容,但在不支持js时图片不能显示;
3,用自定义函数获取:使用在比较复杂的情况,需要手动设置。
具体还是要根据实际情况来选择。

【设置holder】

如果使用了holder占位图,程序会自动设置图片元素显示占位图。
推荐使用loading图片来设置,但loading图往往跟原图的尺寸是不同的。
如果img设置了原图宽高,又想保持loading图的尺寸,把它设为背景就可以了。
但这样在ie下,不设置src默认会有一个小图标。
要去掉这个小图标可以设置holder为一个透明图片的链接,或者参考这里的TRANSPARENT“做”一个透明图片。
实例中也是这样设置的,可以参考一下。

【执行程序】

千万不能在window.onload中执行,因为那时图片都已经加载完了。
而应该在容器后面(window的话是文档结尾)或DOMContentLoaded中执行。

程序源码

代码

var ImagesLazyLoad = $$.wrapper(function(options) {
this._initialize( options );
//如果没有元素就退出
if ( this.isFinish() ) return;
//初始化模式设置
this._initMode();
//进行第一次触发
this.resize(true);
}, LazyLoad);
$$.extend( ImagesLazyLoad.prototype, {
//初始化程序
  _initialize: function(options) {
    LazyLoad.prototype._initialize.call(this, [], options);
//设置子类属性
var opt = this.options;
this.onLoad = opt.onLoad;
var attribute = this._attribute = opt.attribute;
//设置加载图片集合
var getSrc = opt.getSrc,
        filter = $$F.bind( this._filter, this,
                opt["class"],
                getSrc ? function(img){ return getSrc(img); }
                    : function(img){ return img.getAttribute( attribute ) || img.src; },
                opt.holder
            );
this._elems = $$A.filter(
            opt.images || this._container.getElementsByTagName("img"), filter
        );
//判断属性是否已经加载的方法
this._hasAttribute = $$B.ie6 || $$B.ie7
? function(img){ return attribute in img; }
        : function(img){ return img.hasAttribute( attribute ); };
  },
//设置默认属性
  _setOptions: function(options) {
return LazyLoad.prototype._setOptions.call(this, $$.extend({//默认值
        images:        undefined,//图片集合
        attribute:    "_lazysrc",//保存原图地址的自定义属性
        holder:        "",//占位图
"class":    "",//筛选样式
        getSrc:        undefined,//获取原图地址程序
        onLoad:        function(){}//加载时执行
    }, $$.extend( options, {
        onLoadData:    this._onLoadData
    })));
  },
//筛选整理图片对象
  _filter: function(cls, getSrc, holder, img) {
if ( cls && img.className !== cls ) return false;//排除样式不对应的
//获取原图地址
var src = getSrc(img);
if ( !src ) return false;//排除src不存在的
if ( src == img.src ) {
//排除已经加载或不能停止加载的
if ( img.complete || $$B.chrome || $$B.safari ) return false;
        img.removeAttribute("src");//移除src
    }
if ( holder ) { img.src = holder; }
//用自定义属性记录原图地址
    img.setAttribute( this._attribute, src );
return true;
  },
//显示图片
  _onLoadData: function(img) {
var attribute = this._attribute;
if ( this._hasAttribute( img ) ) {
        img.src = img.getAttribute( attribute );
        img.removeAttribute( attribute );
this.onLoad( img );
    }
  }
});

完整实例下载

转载请注明出处:http://www.cnblogs.com/cloudgamer/

如有任何建议或疑问,欢迎留言讨论。

如果觉得文章不错的话,欢迎点一下右下角的推荐。

最新作品:ImagesLazyLoad 图片延迟加载效果

分享到:
评论

相关推荐

    图片延迟加载(imageLazyLoad)

    - **ImagesLazyLoad.htm**:这可能是一个示例HTML页面,展示了如何在实际项目中应用图片延迟加载。它包含了延迟加载的图片元素和必要的JavaScript代码引用。 - **LazyLoad.js**:这是实现图片延迟加载功能的...

    延迟加载 html优化

    同时,为了确保兼容性和性能,这类库还会考虑预加载机制,即在用户即将看到的内容之前就开始加载,提供更流畅的过渡效果。 另一个文件`CJL.0.1.min.js`可能是另一个版本的延迟加载库,或者具有相似功能的脚本。"CJL...

    CJL.js:Cloudgamer JavaScript 库

    Cloudgamer JavaScript Library Author: Project in Chinese ...[ImagesLazyLoad 图片延迟加载效果] () [Lazyload 延迟加载效果] () [JavaScript 图片上传预览效果] () [简便无刷新文件上传系统] () Read

    jquery image lazy load

    "jQuery Image Lazy Load" 是一种优化策略,它延迟非视口内的图片加载,直到用户滚动到即将可见的位置。这种方式可以显著提升网页的初始加载速度,提供更好的用户体验。 ### 一、jQuery 概述 jQuery 是一个广泛...

    ImageZoom 图片放大镜效果(多功能扩展篇)

    主要扩展了原图和显示框的展示模式,有以下几种模式: “follow” 跟随模式:显示框能跟随鼠标移动的效果; “handle” 拖柄模式:原图上有一个拖柄来标记显示范围; “cropper” 切割模式:原图用不透明的来标记...

Global site tag (gtag.js) - Google Analytics