蔡繁荣
蔡繁荣
  • 发布:2015-07-01 14:41
  • 更新:2022-08-24 17:15
  • 阅读:27048

分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0

分类:MUI

今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载。

然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写了一个轻量级的懒加载功能模块,而且支持图片缓存到本地哦~~~

欢迎各位拍砖,交流碰撞思想!

升级日志

v1.1.0 build 20160107
1、已增加 @LFZ 的代码,不用重复下载两次服务器端的图片
2、新增图片加载淡入特效
3、新增图片加载完成后回调
4、修改data-src为data-lazyload

功能特性

~原生实现,不依赖任何前端框架
~ajax动态加载支持图片懒加载
~支持图片缓存到本地
~轻量模块化

如何使用

1、引入md5.min.js,因为依赖js版md5函数,用于将图片url转换为32位md5

<script s r c="md5.min.js"></script>

2、在头部js包含下面的lazyload方法函数,否则可能报错函数未定义

3、HTML代码使用ajax动态生成如下img标签,src为默认图片,data-src填写图片网络地址,并且必须包含onload事件来触发懒加载功能。

<img s r c="placehold.jpg" data-lazyload="http://...jpg"  onload="lazyload(this)" />

注意:因为函数依赖plus.io和plus.downloader接口,所以在plus还没ready的时候img onload执行lazyload可能会报错,lazyload比plus先执行完毕。

当然,在真实环境中,不管是商品列表、订单列表等,我们的图片一般都是动态加载的,所以问题不大。
在代码的写法策略上需要使用动态加载方式,尽量不使用写死在html里面。

4、添加.img-lazyload 支持图片淡入样式

@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
.img-lazyload{-webkit-animation: fadeIn 350ms linear 0ms 1 normal both;animation: fadeIn 350ms linear 0ms 1 normal both;opacity:1;}

5、图片默认缓存到_downloads/image/目录下

活动图

函数源代码

/**  
 * 图片懒加载  
 * @param {Object}   obj       DOMElement  
 * @param {Function} callback  加载完成回调函数  
 *   
 * @author fanrong33  
 * @version 1.1.0 build 20160107  
 */  
function lazyload(obj, callback){  
    var debug = false; // 默认打印调试日志  
    if(obj.getAttribute('data-loaded')){  
       return;   
    }  

    var image_url = obj.getAttribute('data-lazyload');  
    debug && console.log(image_url);  

    // 1. 转换网络图片地址为本地缓存图片路径,判断该图片是否存在本地缓存  
    // http://...jpg -> md5  
    // 缓存目录 _downloads/image/(md5).jpg  
    var image_md5           = md5(image_url);  
    var local_image_url     = '_downloads/image/'+image_md5+'.jpg'; // 缓存本地图片url  
    var absolute_image_path = plus.io.convertLocalFileSystemURL(local_image_url); // 平台绝对路径  

    // new temp_img 用于判断图片文件是否存在  
    var temp_img = new Image();  
    temp_img.src = absolute_image_path;  
    temp_img.onload = function(){  
        debug && console.log('存在本地缓存图片文件'+local_image_url+',直接显示');  

        // 1.1 存在,则直接显示(本地已缓存,不需要淡入动画)  
        obj.setAttribute('src', absolute_image_path);  
        obj.setAttribute('data-loaded', true);  
        obj.classList.add('img-lazyload');  

        callback && callback();  
        return;  
    }  
    temp_img.onerror = function(){  
        debug && console.log('不存在本地缓存图片文件');  

        // 1.2 下载图片缓存到本地  
        debug && console.log('开始下载图片'+image_url+' 缓存到本地: '+local_image_url);  
        function download_img(){  
            var download_task = plus.downloader.createDownload(image_url, {  
                filename: local_image_url // filename:下载任务在本地保存的文件路径  
            }, function(download, status) {  
                if(status != 200){  
                    // 下载失败,删除本地临时文件  
                    debug && console.log('下载失败,status'+status);  
                    if(local_image_url != null){  
                        plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {  
                            entry.remove(function(entry) {  
                                debug && console.log("临时文件删除成功" + local_image_url);  
                                // 重新下载图片  
                                download_img();  
                            }, function(e) {  
                                debug && console.log("临时文件删除失败" + local_image_url);  
                            });  
                        });  
                    }  
                }else{  
                    // 把下载成功的图片显示  
                    // 将本地URL路径转换成平台绝对路径  
                    obj.setAttribute('src', plus.io.convertLocalFileSystemURL(local_image_url));  
                    obj.setAttribute('data-loaded', true);  
                    obj.classList.add('img-lazyload');  

                    callback && callback();  
                }  
            });  
            download_task.start();  
        }  
        download_img();  
    }  

}
52 关注 分享
BoredApe 粥冰 羊羽亻子 Loadingz hilongjw wenju Nation LFZ 豆花饭 豆腐果lyl DCloud_UNI_CHB 后海 G_jia DCDDD 老贪嗔痴 lauhome ztingjian 球风无痕 王帆 信不过你开车 建东 EM b***@msn.com 5675557 l***@boholo.com chenyumu 地球人 小白免 4***@qq.com 老火 成都H5 牛顿爱吃苹果 陨落星辰 jwenlee shwanYu 1***@qq.com WinXP qiuxiaojun ROBOT10086 3***@qq.com 5***@qq.com 1***@qq.com [已删除] android_yang 全栈开发南京 杨婆婆管家家 n***@qq.com 7***@qq.com 邱水仙 1***@qq.com

要回复文章请先登录注册

约洛

约洛

想把网络图片改为本地图片怎么写?? data-lazyload=img/??"
2016-04-19 16:22
b***@msn.com

b***@msn.com

留下了,谢谢
2016-04-14 10:06
建东

建东

为什么不管用啊 谁都demo给我一份呗 。 万分感谢 急用。 353309829@qq.com
2016-03-28 21:30
XCODE

XCODE

#################################################
## 解决图片没有下载完整导致,加载异常问题 ##
#################################################



/**
* 图片懒加载
* @param {Object} obj DOMElement
* @param {Function} callback 加载完成回调函数
*
* @author fanrong33
* @version 1.1.0 build 20160107
*/
function lazyload(obj, callback) {
var debug = false; // 默认打印调试日志
if (obj.getAttribute('data-loaded')) {
return;
}

var image_url = obj.getAttribute('data-lazyload');
debug && console.log(image_url);


// 1. 转换网络图片地址为本地缓存图片路径,判断该图片是否存在本地缓存
// http://...jpg -> md5
// 缓存目录 _downloads/image/(md5).jpg
var image_md5 = md5(image_url);
var local_image_url = '_downloads/image/' + image_md5 + '.jpg'; // 缓存本地图片url
var absolute_image_path = ""; // 平台绝对路径
plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {
absolute_image_path = entry.toRemoteURL();
var temp_img = new Image();
entry.file(function(file) {
var totalSize = localStorage.getItem(image_md5 + "totalSize");
debug && console.log(file.size + " " + totalSize);
if (file && file.size == totalSize) {
//此时文件是完整的,可以直接进行展示。
debug && console.log('存在本地缓存图片文件' + local_image_url + ',直接显示');

// 1.1 存在,则直接显示(本地已缓存,不需要淡入动画)
obj.setAttribute('src', absolute_image_path);
obj.setAttribute('data-loaded', true);
obj.classList.add('img-lazyload');
callback && callback(obj);
} else {
//文件没有下载完整,进行下载处理。
debug && console.log('不存在本地缓存图片文件');

// 1.2 下载图片缓存到本地
debug && console.log('开始下载图片' + image_url + ' 缓存到本地: ' + local_image_url);
download_img(image_url, local_image_url, image_md5, obj, callback);
}
});
}, function(Ex) {
//文件不存在,进行下载处理。
debug && console.log('不存在本地缓存图片文件');
// 1.2 下载图片缓存到本地
debug && console.log('开始下载图片' + image_url + ' 缓存到本地: ' + local_image_url);
download_img(image_url, local_image_url, image_md5, obj, callback);
});
}

/**
*
* @param {Object} image_url 文件下载地址
* @param {Object} local_image_url 文件本地缓存地址
* @param {Object} image_md5 文件名md5加密
* @param {Object} obj img对象
* @param {Object} callback 回调方法
*/
function download_img(image_url, local_image_url, image_md5, obj, callback) {
var download_task = plus.downloader.createDownload(image_url, {
filename: local_image_url // filename:下载任务在本地保存的文件路径
}, function(download, status) {
localStorage.setItem(image_md5 + "totalSize", download.totalSize);
if (status != 200) {
// 下载失败,删除本地临时文件
debug && console.log('下载失败,status' + status);
if (local_image_url != null) {
plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {
entry.remove(function(entry) {
debug && console.log("临时文件删除成功" + local_image_url);
// 重新下载图片
download_img();
}, function(e) {
debug && console.log("临时文件删除失败" + local_image_url);
});
});
}
} else if (status === 200) {
// 把下载成功的图片显示
// 将本地URL路径转换成平台绝对路径
obj.setAttribute('src', plus.io.convertLocalFileSystemURL(local_image_url));
obj.setAttribute('data-loaded', true);
obj.classList.add('img-lazyload');
callback && callback(obj);
}
});
download_task.start();
}
2016-03-25 15:41
蔡繁荣

蔡繁荣 (作者)

回复 王帆 :
文章末尾附件
2016-03-08 12:07
王帆

王帆

楼主你的 md5 加密哪来的 分享下呗
2016-03-07 15:04
柏原崇

柏原崇

为啥还是会报plus is not defined的错误,我参考了楼上LFZ的代码~
2016-01-21 10:55
后海

后海

都是js大神
2015-12-23 12:32
风雪无血

风雪无血

回复 风雪无血 :
解决了~
2015-11-03 10:27
风雪无血

风雪无血

为什么我把js放头部还是报lazyload is not defined??
2015-11-03 09:31