Josh
Josh

Reputation: 664

Drawing on visible canvas from offscreen canvas

When I try to draw on a visible canvas using the image from an offscreen canvas, I get strange errors, and the image isn't drawn until I reload the page in some way.

Here's my example code. Insert any small image file.

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
    <canvas id="visible canvas" width=800 height=600></canvas>
    <script>
        // load the image
        var img = new Image();
        img.src = "smallimage.png";

        // create a hidden canvas, exactly the size of our small image
        var hidden_canvas = document.createElement("canvas");
         hidden_canvas.width = img.width;
         hidden_canvas.height = img.height;
        var hidden_context = hidden_canvas.getContext("2d");        

        // draw the image on the hidden canvas
        hidden_context.drawImage(img, 0, 0);

        // set up the visible canvas
        var visible_canvas = document.getElementById("visible canvas");
        var visible_context = visible_canvas.getContext("2d");

        // draw on the visible canvas using the image from the hidden canvas
        visible_context.drawImage(hidden_canvas,0,0);
    </script>
</body>
</html>

In Firefox, the first time I load the page, I get a blank page and this error in Firebug: InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. It says the error is in the last line: visible_context.drawImage(hidden_canvas,0,0);

Then I refresh the page, and it works properly.

In Chrome, I also get a blank page (with no errors). If I hit enter in the address bar, it loads again and works properly.

I have tried running from a local server, and I still get the same results.

Can someone help me understand the problem? Why won't it work the first time I load the page?

Upvotes: 0

Views: 2946

Answers (1)

Patrick Evans
Patrick Evans

Reputation: 42736

This is because the rest of your code is running before the image has had time to load. And it works on reload because the image is cached and so loads immediately.

Use the iamge's onload property to set a load event listener and execute your code when the image is ready

var img = new Image();
img.onload = function(){
    // create a hidden canvas, exactly the size of our small image
    var hidden_canvas = document.createElement("canvas");
    hidden_canvas.width = img.width;
    hidden_canvas.height = img.height;
    var hidden_context = hidden_canvas.getContext("2d");        

    // draw the image on the hidden canvas
    hidden_context.drawImage(img, 0, 0);

    // set up the visible canvas
    var visible_canvas = document.getElementById("visible canvas");
    var visible_context = visible_canvas.getContext("2d");

    // draw on the visible canvas using the image from the hidden canvas
    visible_context.drawImage(hidden_canvas,0,0);    
};

img.src = "http://placehold.it/250x250";

JSFiddle Demo;

Upvotes: 2

Related Questions