Reputation: 945
I have been staring at this too long, and need some help. I have the following simplified fiddle example that works in IE, but not in Chrome (no errors, just no images get redrawn after canvas is cleared in Chrome):
var myApp = {};
// redraw function that will be called during init and then will loop.
myApp.redrawFunction = function() {
window.requestAnimationFrame(myApp.redrawFunction);
// clear canvas (not needed in this simplified example, but I need it in my real app)
myApp.drawingContext.clearRect(0, 0, myApp.canvas.width, myApp.canvas.height);
// draw an image.
var myImage = new Image();
myImage.onload = function() {
myApp.drawingContext.drawImage(myImage, 0, 0);
};
myImage.src= "http://www.w3.org/html/logo/img/mark-word-icon.png";
};
// initialize
$(function () {
// setup the animation frame objects.
window.requestAnimationFrame = window.requestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.msRequestAnimationFrame;
window.cancelAnimationFrame = window.CancelAnimationFrame
|| window.CancelRequestAnimationFrame
|| window.mozCancelAnimationFrame
|| window.mozCancelRequestAnimationFrame
|| window.msCancelAnimationFrame
|| window.msCancelRequestAnimationFrame
|| window.webkitCancelAnimationFrame
|| window.webkitCancelRequestAnimationFrame;
// get canvas references.
myApp.canvas = $("canvas")[0];
myApp.drawingContext = myApp.canvas.getContext("2d");
$(myApp.canvas).css("background-color", "#999999");
// update canvas size to fill screen.
myApp.canvas.width = $(window).width();
myApp.canvas.height = $(window).height();
$(window).resize(function (){
myApp.canvas.width = $(window).width();
myApp.canvas.height = $(window).height();
});
// start redraw loop
myApp.redrawFunction();
});
If you open this fiddle in IE 10, it works (you see a logo). If you open this in Chrome, you see a blank canvas, showing that my drawImage call did not work after clearing the canvas. Any ideas what I am missing?
Upvotes: 3
Views: 3634
Reputation: 92274
The problem is that you're clearing the canvas, then you are waiting for an image to load, when the image loads, the animation runs again, clears the canvas and wait for the new image to load. Therefore, you always see the canvas state immediately after calling clearRect
, because when you call drawImage
, the animation routine will kick in again before you get a chance to see the result of drawImage()
and you'll see the result of clearRect()
.
The solution is not to clear the canvas until the image is ready to be painted. http://jsfiddle.net/JrLh7/6/
var myApp = {};
// redraw function that will be called during init and then will loop.
myApp.redrawFunction = function() {
// Don't clear the canvas here, it will be empty until the onload handler is called
var myImage = new Image();
myImage.onload = function() {
// Clear canvas and immediately paint the image
myApp.drawingContext.clearRect(0, 0, myApp.canvas.width, myApp.canvas.height);
myApp.drawingContext.drawImage(myImage, 0, 0);
// Then you should ask for another frame after you've finished painting the canvas
window.requestAnimationFrame(myApp.redrawFunction);
};
myImage.src= "http://www.w3.org/html/logo/img/mark-word-icon.png";
};
Note
It doesn't make a lot of sense to have an animation routine that is asynchronous. If so, at the very least, you shouldn't request a new animation frame until you've finished painting the canvas.
Upvotes: 3