web-dev-qa-db-fra.com

Attendez que l'image soit chargée avant de continuer

Je développe un jeu en utilisant JavaScript et canvas. Au fur et à mesure que le jeu se charge, toutes les images qui seront utilisées sont mises en cache.

En observant la chronologie des ressources, je constate que le code suivant déclenche une demande asynchrone:

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

Le moteur continuera à fonctionner, commençant éventuellement à dessiner et à jouer le niveau. Les images chargées après la première image peuvent ne jamais apparaître en raison de l'écrêtage (c'est-à-dire qu'elles ne sont pas "sales").

J'ai donc testé les éléments suivants:

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

Les sorties de console résultantes dans l'ordre où elles se produisent sont:

  • begin
  • end
  • loaded!

Je cherche un moyen similaire à $.ajax avec async: false pour effectuer le chargement. Je ne sais pas comment ... merci d'avance pour votre aide! J.

31
Jem

Vous ne devez pas faire d'appels synchrones (pas même AJAX), mais placez simplement votre code dans le rappel approprié:

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

Ensuite, utilisez-le comme ceci:

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

Si vous voulez passer des arguments supplémentaires, vous pouvez le faire comme ceci:

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

Si vous souhaitez charger plusieurs éléments et devez attendre qu'ils se terminent tous, envisagez d'utiliser l'objet jQuery différé :

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

Dans la fonction de chargement des sprites, vous faites quelque chose comme ceci:

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/

59
ThiefMaster

Cette question est ancienne, mais il existe un moyen de le faire sans nécessiter jquery, OR gel du navigateur.

Dans image1.onLoad, faites-le charger image2.
Dans image2.onLoad, faites-le charger image3.
Dans image3.onLoad, faites-le charger image4.
....
Dans l'imagen.onLoad lui fait charger votre fonction principale.

Je ne sais pas si c'est la MEILLEURE façon de le faire, mais c'est mieux que de geler le navigateur, au moins.
Vous pouvez également charger tous vos fichiers audio ou toutes les autres ressources dont vous avez besoin, ou tout autre javascript dont vous avez besoin pour exécuter.

Le gel du navigateur n'est pas nécessaire

2
Interpolate

J'ai ce problème avec Canvas, j'ai essayé votre solution, mais la meilleure et la plus simple méthode qui fonctionne est:

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);
    };
}
0
ettore ct