2011-08-11 17 views
9

Estoy jugando con el elemento canvas en HTML5 y he notado un comportamiento peculiar. En la carga inicial, una imagen que estoy mostrando no se muestra. Sin embargo, cuando actualizo el navegador, se muestra correctamente. He usado IE9 y Chrome. Ambos se comportan de manera idéntica. El código JavaScript se parece a esto:¿Por qué la imagen no se muestra al cargarse, pero se muestra al actualizar?

window.onload = load; 
function load() { 
    var canvas = document.getElementById("canvas"); 
    var context = canvas.getContext("2d"); 
    context.fillRect(0, 0, 640, 400); 
    var image = new Image(); 
    image.src = "Images/smiley.png"; 
    context.drawImage(image, 50, 50); 
} 

El rectángulo dibuja correctamente en ambas ocasiones, es la sonrisa que sólo muestra en una actualización del navegador.

Estoy en proceso de aprender HTML5 y JavaScript. Estoy seguro de que estoy haciendo algo estúpido, pero no puedo resolverlo.

Respuesta

17

Las imágenes se cargan de forma asíncrona, por lo que solo después de la actualización se carga lo suficientemente rápido porque está en caché. Normalmente, aún no está cargado en el momento de llamar al drawImage. Utilice onload:

var image = new Image(); 
image.src = "Images/smiley.png"; 
image.onload = function() { 
    context.drawImage(image, 50, 50); 
}; 
+0

Gracias. Sabía que era algo simple. –

3

Esto sucedió conmigo, así (sólo para IE9 para mí) de todos modos, he encontrado una solución sencilla.

Establezca el fondo del lienzo en la imagen inicial que desea visualizar.

var canvas = document.getElementById("canvas"); 
canvas.style.background="url('image.png')"; 

Eso debería funcionar!

+0

pimvdb me acabo de dar cuenta es probablemente una mejor manera. – Jacob

0

En realidad, incluso usando image.onload = function() {}, puede tener problemas. Use esta técnica (eso no es para nada lo que estoy diciendo), sino muévala al pie de la página.

Como ejemplo, tengo un sitio de redes sociales que utiliza un lienzo para mostrar la foto de perfil (URI almacenado en el DB), la imprime en lienzo y luego superpone un logotipo.

<section id="content"> 
    <article id="personalbox" > 
     <h2>Hi! My name is {profile_name}</h2> 
     <a id="friendbutton" href=""><img src="views/default/images/friend.png" width="12" height="12" /><span>Add {profile_name} as a friend?</span></a> 
     <video id="profilevideo" width="240" height="144">DEBUG: Video is not supported.</video> 
     <canvas id="profilecanvas" width="240" height="144" >DEBUG: Canvas is not supported.</canvas> 
     <a id="gallerytextlink" href="gallery.html" >Click to visit {profile_name} Gallery</a> 
     <table id="profileinfotable1"> 

...

</section> 

<script type="text/javascript"> 
    function init() { 
    var cvs = document.getElementById("profilecanvas"); 
    var ctx = cvs.getContext("2d"); 
    var img = new Image(); 
    img.src = "uploads/profile/{profile_photo}"; 
    img.onload = function() { 
     // Ignore. I was playing with the photo. 
     ctx.drawImage(img, 42, 32, 186, 130, cvs.width/2 - (186-42)/2, cvs.height/2 - (130-32)/2, 186-42, 130-32); 
     drawLogo(cvs,ctx); 
    } 
    } 

    function drawLogo(cvs,ctx) { 
    var logo   = "Enter Logo Here."; 
    ctx.fillStyle  = "rgba(36,36,36,0.6)";   
    ctx.strokeStyle = "rgba(255,255,255,0.3)"; 
    ctx.font   = "bold italic 6pt Serif"; 
    ctx.textAlign  = "left"; 
    ctx.textBaseline = "middle" ; 

    ctx.save(); 
    ctx.strokeText(logo, 4, cvs.height-11); 
    ctx.strokeText(logo, 6, cvs.height-11); 
    ctx.strokeText(logo, 4, cvs.height-9); 
    ctx.strokeText(logo, 6, cvs.height-9); 
    ctx.fillText(logo, 5, cvs.height-10); 
    ctx.restore(); 
    } 

    window.onload = init; 
</script> 

Idealmente, esto sería ir hasta el final en la parte inferior antes de la etiqueta final </body>, pero me lo puso más alta debido a mi sistema de plantillas. Aparentemente, esto le da a la imagen tiempo para cargarse después de que el elemento de lienzo se haya dibujado en la pantalla y esté listo para recibir datos.

No puedo confiar en establecer el fondo del lienzo, y no tengo ganas de lidiar con las actualizaciones. Por alguna razón, solo incluir el script con img.onload = function() {} no fue suficiente. Muévala más abajo y ahórrese los dolores de cabeza.

Cuestiones relacionadas