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

分享基于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

要回复文章请先登录注册

蔡繁荣

蔡繁荣 (作者)

回复 LFZ :
赞!
2015-10-25 13:25
豆花饭

豆花饭

谢谢分享
2015-10-25 05:29
LFZ

LFZ

我修改了部分代码,不用重复下载两次服务器端的图片。
```javascript
function lazyload(obj) {
var debug = false; // 默认打印调试日志
if (obj.getAttribute('data-loaded')) {return;}
var image_url = obj.getAttribute('data-src');
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);
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:下载任务在本地保存的文件路径plus.io.convertLocalFileSystemURL( url );
}, 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);
}
});
download_task.start();
}
}
}
```
2015-10-24 22:47
蔡繁荣

蔡繁荣 (作者)

回复 YingYu :
好像没法一次性下载多张图片,downloader创建的只是个task, 要调用start() 才开始进行下载,所以可以用队列的方式去管理,来控制同步下载数。具体还是要看下api文档
2015-09-16 14:09
YingYu

YingYu

回复 蔡繁荣 :
就是一次性下载批量图片,看 Downloader 不是很熟悉, 创建一个下载任务 能下载批量图片?还是一个下载任务只能下载一张图片? 不是很懂!拜托了
2015-09-16 11:22
蔡繁荣

蔡繁荣 (作者)

回复 YingYu :
一次要批量下载300张图片?
2015-09-16 10:13
YingYu

YingYu

大神们,我想问如果要下载200/300张图片的话,createDownload 这个是怎么操作的?求指导
2015-09-16 09:40
wenju

wenju

大神,原来你已经把最开始的帖子修改优化了好多 兜兜转转又回来看这个贴了
2015-09-10 20:28
wenju

wenju

被自己坑了 我的列表有很多图片 这样plus.downloader.createDownload会创建好多线程 导致手机一下子就发烫了 ... 看来得试试你说的Canvas, 不知道怎么监听和保存图~~~~(>_<)~~~~
2015-07-28 09:46
Loadingz

Loadingz

回复 蔡繁荣 :
嗯,确实如此,非常感谢,你的分享给了我很大帮助
2015-07-25 08:33