img.onload 处理单张和多张图片加载

@一棵菜菜  November 13, 2018

先来了解下new Image()

new Image()

创建一个Image对象:var a = new Image();   
定义Image对象的src: a.src = ”xxx.gif”;   
这样做就相当于给浏览器缓存了一张图片。

图像对象

建立图像对象:图像对象名称=new Image([宽度],[高度])

图像对象的属性: border complete height hspace lowsrc name src vspace width

图像对象的事件:onabort onerror onkeydown onkeypress onkeyup onload

注意:src 属性一定要写到 onload 的后面,否则程序在 IE 中会出错。而且可能图片已经加载完成了,才执行onload已经晚了。

可以通过Image对象的complete 属性来检测图像是否加载完成(每个Image对象都有一个complete属性,当图像处于装载过程中时,该属性值false,当发生了onload、onerror、onabort中任何一个事件后,则表示图像装载过程结束(不管成没成功),此时complete属性为true)

注:
ie 火狐等大众浏览器均支持 Image对象的onload事件。
ie8及以下、opera 不支持onerror事件。

参考文章

单张图片加载

var img = new Image();
// 先onload,再赋值地址src
img.onload = function(){
    //TODO
}
img.src = "";

多张图片加载问题

目前要使用 canvas 进行绘图,但是要加载多张图片资源,使用了js的图片对象进行处理

法一【普通方法】

每一个onload后触发一个相同的callback,累计一个图片加载数量,若数量等于需要加载图片的数量后,执行你要的绘图函数。

/**
* srcs 图片地址的数组
* suc 全部加载后回调一个JSON包含所有图片的尺寸
**/
function getImages(srcs,suc){
    var num=0,infos=[];    
    for(var i=0;i<srcs.length;i++){
        (function loadimg(url){
            var img=new Image();
            img.onload=function(){
                // if(this.complete){
                    num++;
                    infos.push({
                        w:this.width,
                        h:this.height
                    });
                    num==srcs.length && suc&&suc(infos);
                // }
            }
            img.src=url;
        })(srcs[i]);
    }
}

// 简单的写了下,没做错误处理,需要的话,可以适当的加上去

法二 异步加载Promise、defer法

使用 jQuery 中的 Deferred 对象

转载,查看原文

Deferred 对象是从 jQuery 1.5.0 版本开始引入的一个新功能,详细介绍可以见 官方文档。

简单的说,Deferred 对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题, 对那些操作提供了更好的控制,以及统一的编程接口。

阮一峰有一篇文章是介绍 Deferred 对象的,写的比较详细,对于入门比较有用。

jQuery的deferred对象详解

在这里,我们用到了:

deferred.resolve(): Resolve a Deferred object and call any doneCallbacks with the given args.
deferred.when(): Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.
deferred.done(): Add handlers to be called when the Deferred object is resolved.

关键代码:

undefinedvar defereds = [];
$imgs.each(function() {    
  var dfd = $.Deferred();    
  $(this).load(dfd.resolve);    
  defereds.push(dfd);
});
$.when.apply(null, defereds).done(function() {    
  console.log('load compeleted');
});

基本思路

每加载完一张图片 resolve(),when() 当所有的 Deferred 完成便执行 done()。

注: 因为 $.when 支持的参数是 $.when(dfd1, dfd2, dfd3, ...),所以我们这里使用了 apply 来接受数组参数。

总结

onload函数要写在改变src前,这样确保了onload函数一定会被调用
complete只是变向的在判断img是否已经触发了load事件,而且是不精准的判断
complete在不同浏览器下,表现不一致,不建议使用
无论浏览器是否存在图片缓存,重新请求图片地址,都会触发onload事件

'总结'参考:《图片的异步加载与onload函数》

添加新评论