在继续之前等待图像加载

IT技术 javascript image asynchronous canvas load
2021-03-15 19:31:15

我正在使用 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与 with类似的方法async: false来执行加载。无法弄清楚如何......提前感谢您的帮助!J。

3个回答

你不应该进行任何同步(甚至 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延迟对象:

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/

感谢您的回复。我忘了提到,这段代码是由父级调用的函数名称“loadSprite(name)”的一部分。该父级从循环中调用它,例如“对于每个精灵 loadSprite(name)”。我需要能够中断处理,导致该方法仅在加载图像时返回。任何的想法?
2021-05-06 19:31:15
如果不冻结浏览器,您就无法做到这一点。我将更新我的答案以显示(该)正确的解决方案。
2021-05-10 19:31:15
嘿,谢谢,这很有趣。我根本不知道那个延期的对象!
2021-05-10 19:31:15
这是一个很好的解释,说明如何以没有已经延迟的对象(如 $.ajax)的方式使用延迟对象,而不是与动画结合使用。非常有用且解释得很好 - 谢谢。
2021-05-14 19:31:15

这个问题很老了,但是有一种方法可以在不需要 jquery 或冻结浏览器的情况下做到这一点。

在 image1.onLoad 中,让它加载 image2。
在 image2.onLoad 中,让它加载 image3。
在 image3.onLoad 中,让它加载 image4。
....
在图像n .onLoad 让它加载你的主要功能。

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

不需要冻结浏览器

这就是我目前的做法(使用 Canvas 的第一晚),但看起来很乱。有更好的方法吗?我已经尝试为加载的资源设置真/假标志并使用 do/while 循环,但除此方法外我无法进行任何工作。
2021-04-30 19:31:15
我最终构建了一个自定义回调方法,该方法增加了资源计数器(并将其与资源数组的长度进行了比较)并且如果它们是不同的值则不执行任何操作,或者如果值匹配则开始在画布上绘制(这意味着所有资源已加载)。
2021-05-17 19:31:15
不确定。我的项目只需要一两个资源,所以我从未涉足整个资源加载场景。我相信有更好的方法可以做到这一点。祝你好运!:)
2021-05-21 19:31:15

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

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);
    };
}