2011-12-27 34 views
25

Estoy desarrollando un juego usando JavaScript y canvas. A medida que el juego se carga, todas las imágenes que se utilizarán se almacenan en caché.Espere a que se cargue la imagen antes de continuar

Observando la línea de tiempo de los recursos, veo que el siguiente código desencadena una solicitud asincrónica:

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

El motor sigue ejecutando, con el tiempo comienza a dibujar y jugar el nivel. Es posible que las imágenes que se cargan después de pintar el primer fotograma nunca aparezcan debido a la saturación (es decir, que no se "ensucien").

Así que prueba los siguientes grupos:

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

Las salidas de la consola resultantes en el orden en que se producen son:

  • begin
  • end
  • loaded!

Estoy buscando una manera similar a $.ajax con async: false para realizar la carga. No puedo entender cómo ... gracias de antemano por su ayuda! J.

Respuesta

55

Usted no debe hacer nada síncrona (ni siquiera AJAX) llamadas sino simplemente poner el código en la devolución de llamada apropiada:

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

Entonces utilizar de esta manera:

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

Si desea pasar argumentos adicionales, puede hacerlo así:

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

Si desea cargar varios elementos y la necesidad de esperar a que todos ellos para terminar, puede utilizar el objeto jQuery deferred:

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

En la función de la carga de los sprites, se hace algo como esto:

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/

+0

Gracias por su respuesta. Me olvidé de mencionar, este código es parte de un nombre de función "loadSprite (nombre)" que está siendo llamado por un padre. Ese padre lo llama desde un bucle como "para cada sprite loadSprite (nombre)". Necesito poder interrumpir el procesamiento, haciendo que el método vuelva solo cuando se cargó la imagen. ¿Alguna idea? – Jem

+0

No puede hacer esto sin congelar el navegador. Actualizaré mi respuesta para mostrar una (la) solución adecuada. – ThiefMaster

+0

Hola, gracias, es muy interesante. ¡No sabía nada sobre ese objeto diferido! – Jem

2

esta pregunta es viejo, pero hay una manera de hacer esto sin necesidad de jQuery, O freezin g el navegador.

En image1.onLoad, haga que cargue imágenes2.
En image2.onLoad, haz que cargue image3.
En image3.onLoad, haz que cargue image4.
....
En la imagen n .onLoad hace que cargue su función principal.

No estoy seguro de si esta es la mejor manera de hacerlo, pero es mejor que congelar el navegador, al menos.
También puede cargar todos sus archivos de audio o cualquier otro recurso que necesite, o cualquier otro javascript que necesite ejecutar.

congelación el navegador no se requiere

+1

Así es como lo estoy haciendo actualmente (la primera noche usando Canvas) pero parece desordenado. ¿Hay una mejor manera de hacerlo? Intenté configurar indicadores de verdadero/falso para los recursos cargados y utilizando los bucles do/while, pero no puedo obtener nada más que este método. – BenM

+1

No estoy seguro. Solo necesito uno o dos recursos para mis proyectos, así que nunca llegué a la escena completa de carga de recursos. Estoy seguro de que hay mejores formas de hacerlo. La mejor suerte para ti! :) – Interpolate

+0

Terminé construyendo un método de devolución de llamada personalizado que aumentaba un contador de recursos (y lo comparaba con la longitud de una matriz de recursos) y no hacía nada si eran valores diferentes o comenzaba a dibujar en el lienzo si los valores coincidían (lo que significa que todos los recursos se han cargado). – BenM

0

tengo este problema con una lona i trató la solución, sino una mejor y más sencilla forma en que funciona es:

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