I'm playing with the canvas element in HTML5 and I have noticed a peculiar behavior. On initial load, an image I'm displaying does not show. However, when I refresh the browser, it displays appropriately. I've used IE9 and Chrome. Both behave identically. The JavaScript code looks like this:
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);
}
The rectangle draws correctly both times, it's the smiley that only shows on a browser refresh.
I'm in the process of learning HTML5 and JavaScript. I'm sure I'm just doing something stupid, but I can't figure it out.
Images load asynchronously, so only after refresh it loads early enough because it's cached. Normally it isn't loaded yet at the time you call drawImage
. Use onload
:
var image = new Image();
image.src = "Images/smiley.png";
image.onload = function() {
context.drawImage(image, 50, 50);
};
This happened with me as well (only for IE9 for me) anyways, i found a simple solution.
Set the background of the canvas to the initial image you wish to display.
var canvas = document.getElementById("canvas");
canvas.style.background="url('image.png')";
That should work!
Actually, even just using image.onload = function() {}
, you can still run into problems. Do use this technique (that's not at all what I'm saying), but move it to the bottom of your page.
As an example, I have a social networking site that uses canvas to show the profile photo (URI stored to the DB), and print it to canvas, then overlay a logo.
<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>
Ideally, this would go all the way at the bottom before the end </body>
tag, but I put it up higher because of my template system. Apparently, this gives the image time to load after the canvas element has been drawn to the screen and is ready to receive input.
I can't rely on setting the background of the canvas, and I have no desire to contend with refreshes. For whatever reason, just including the script with img.onload = function() {}
was not enough. Move it lower, and save yourself the headaches.