在继续之前等待图像加载

Posted

技术标签:

【中文标题】在继续之前等待图像加载【英文标题】:Wait for image to be loaded before going on 【发布时间】:2012-01-28 12:43:57 【问题描述】:

我正在使用 javascriptcanvas 开发游戏。随着游戏的加载,所有将要使用的图像都将被缓存。

观察资源时间线,看​​到如下代码触发了一个异步请求:

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!

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

【问题讨论】:

【参考方案1】:

您不应该进行任何同步(甚至是 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/

【讨论】:

感谢您的回复。我忘了提一下,这段代码是由父级调用的函数名“loadSprite(name)”的一部分。该父级从“for each sprite loadSprite(name)”之类的循环中调用它。我需要能够中断处理,导致该方法仅在加载图像时返回。有什么想法吗? 如果不冻结浏览器,您将无法执行此操作。我将更新我的答案以显示(该)正确的解决方案。 嘿,谢谢,这很有趣。我根本不知道那个延迟对象! 这是一个很好的解释,说明了如何以没有已延迟对象(如 $.ajax)的方式使用 Deferred 对象,并且不与动画结合使用。非常有用且解释得很好 - 谢谢。【参考方案2】:

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

在image1.onLoad中,让它加载image2。 在 image2.onLoad 中,使其加载 image3。 在 image3.onLoad 中,使其加载 image4。 .... 在 imagen.onLoad 中让它加载你的 main 函数。

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

不需要冻结浏览器

【讨论】:

这就是我目前的做法(第一个晚上使用 Canvas),但看起来很乱。有更好的方法吗?我已经尝试为加载的资源设置真/假标志并使用 do/while 循环,但除了这种方法之外,我什么也做不了。 不确定。我的项目只需要一两个资源,所以我从来没有进入整个资源加载场景。我确信有更好的方法来做到这一点。祝你好运! :) 我最终构建了一个自定义回调方法,该方法增加了资源计数器(并将其与资源数组的长度进行了比较),如果它们是不同的值,则要么不执行任何操作,要么开始在画布上绘制,如果值匹配(这意味着所有资源都已加载)。【参考方案3】:

我的画布有这个问题 我尝试了您的解决方案,但一种最佳且简单的方法是:

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

【讨论】:

以上是关于在继续之前等待图像加载的主要内容,如果未能解决你的问题,请参考以下文章

如何实时防止图像大小调整(页面加载期间)

在运行 angular spa 之前等待 $http

为什么不在主线程上加载图像?

等待一个块加载,然后再加载更多

Puppeteer 等待所有图像加载然后截图

用于预加载图像的 Queue.js 一直在等待? (打回来)