等待图像加载后再继续

时间:2011-12-27 13:25:26

标签: javascript image asynchronous canvas load

我正在使用JavaScript和canvas开发游戏。当游戏加载时,将使用所有将要使用的图像。

观察资源时间线,我看到以下代码触发异步请求:

var sprite = new Image();
sprite.src = "sprites/sheet1.png";

引擎将继续执行,最终开始绘制并播放关卡。绘制第一帧后加载的图像可能永远不会因剪裁而出现(即没有“脏”)。

所以我测试了以下内容:

console.log("begin");
var sprite = new Image();
sprite.onload = function() { console.log('loaded!'); };
sprite.src = "sprites/sheet1.png";
console.log("end");

生成的控制台输出顺序为:

  • begin
  • end
  • loaded!

我正在寻找与$.ajax async: false类似的方式来执行加载。无法弄清楚如何...提前感谢您的帮助! 学家

3 个答案:

答案 0 :(得分:60)

您不应该进行任何同步(甚至不是AJAX)调用,而只需将代码放入适当的回调中:

function loadSprite(src, callback) {
    var sprite = new Image();
    sprite.onload = callback;
    sprite.src = src;
}

然后像这样使用它:

loadSprite('sprites/sheet1.png', function() {
    // code to be executed later
});

如果要传递其他参数,可以这样做:

sprite.onload = function() {
    callback(whatever, args, you, have);
};

如果要加载多个元素并需要等待所有元素完成,请考虑使用jQuery deferred对象:

function loadSprite(src) {
    var deferred = $.Deferred();
    var sprite = new Image();
    sprite.onload = function() {
        deferred.resolve();
    };
    sprite.src = src;
    return deferred.promise();
}

在加载精灵的函数中,你可以这样做:

var loaders = [];
loaders.push(loadSprite('1.png'));
loaders.push(loadSprite('2.png'));
loaders.push(loadSprite('3.png'));
$.when.apply(null, loaders).done(function() {
    // callback when everything was loaded
});

http://api.jquery.com/jQuery.when/

答案 1 :(得分:2)

这个问题很老,但有一种方法可以做到这一点而不需要jquery,或冻结浏览器。

在image1.onLoad中,使其加载image2。
在image2.onLoad中,使其加载image3。
在image3.onLoad中,使其加载image4。
.... 在图像 n .onLoad中,使其加载主函数。

我不确定这是否是完全最好的方法,但它至少比冻结浏览器更好。
您还可以加载所有音频文件或您需要的任何其他资源,或者您需要运行的任何其他JavaScript。

不需要冻结浏览器

答案 2 :(得分:0)

我在画布上遇到了这个问题 我尝试了你的解决方案,但最好和最简单的方法是:

function COLPOinitCanvas(imagesfile) {
    COLPOcanvas = document.getElementById("COLPOcanvas");
    COLPOctx = COLPOcanvas.getContext("2d");
    var imageObj = new Image();
    imageObj.src = imagesfile;
    imageObj.onload = function () {
        COLPOctx.drawImage(imageObj, 0, 0, COLPOcanvas.width, COLPOcanvas.height);
    };
}