I have some HTML 5 code that starts out with two black canvases and then updates the canvases one row at a time by drawing a red line for each row. It is supposed to look like a red curtain dropping down over the black background.
The odd part is that at first it looks like random rows (say 5%) are being skipped and left black. I thought I had a bug. But then I noticed that if I resized the browser window that the black lines all turned red. So then I thought it was some sort of browser repaint bug. Then I noticed that both Chrome and Safari have this behavior.
So do you think both these browsers have the same bug or am I doing something wrong?
Interestingly, this issue goes away if both canvases use style=”width:100%; height:100%”.
<html>
<table>
<tr>
<td><canvas id="myCanvas1" style="width:100%; height:100%"></canvas></td>
<td><canvas id="myCanvas2" style="width:200px; height:400px"></canvas></td>
</tr>
</table>
<script type="text/javascript">
var canvases = [document.getElementById("myCanvas1"), document.getElementById("myCanvas2")];
for(var i = 0; i < canvases.length; i++) {
var canvas = canvases[i];
var ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function updateRow(rowNum) {
var done = true;
for(var i = 0; i < canvases.length; i++) {
var canvas = canvases[i];
if(rowNum >= canvas.height) {
return;
}
done = false;
var ctx = canvas.getContext("2d");
var imageDataForRow = ctx.getImageData(0, rowNum, canvas.width, 1);
for(var offset = 0; offset < imageDataForRow.data.length; offset += 4) {
imageDataForRow.data[offset] = 255;
imageDataForRow.data[offset + 1] = 0;
imageDataForRow.data[offset + 2] = 0;
imageDataForRow.data[offset + 3] = 255;
}
ctx.putImageData(imageDataForRow, 0, rowNum);
}
if(!done) {
var paintNextRow = function() {
updateRow(rowNum + 1);
}
setTimeout(paintNextRow, 1);
}
}
updateRow(0);
</script>
This is your problem:
<canvas id="myCanvas1" style="width:100%; height:100%">You are setting the width and height of the Canvas using CSS width and height and not the
<canvas>html attributes. You are literally stretching a canvas sized 300×150 (the default) to skew across the entire screen.You need to define the width/height either in the canvas tag:
<canvas width="500" height="500">or in code:
And not by CSS. If you did this:
<canvas style="width: 500px; height: 500px;">Then you would have a 300×150 canvas (the default size) that was scaled/warped to be 500×500, which is almost certainly what you’re getting.
It looks like you want to have the canvas width change dynamically. This is OK, but you have to do one of a few things. One would be to use the window’s
onresizeevent, and set the canvas width equal to the div’s clientWidth every time this happens (if the clientWidth has changed of course). The other would be to do a simple general timer to check for the same thing every half-second or so, and setcanvas.widthequal to thediv.style.clientWidth.(I wrote the above freehand so there might be a typo, but you get the idea)