0

I have an issue I'm having a hard time believing... It seems that when I draw to a dynamically created canvas in Firefox it wont render the first time that source is run... It seems to happen the first time the JavaScript in question is run either by modifying the source or visiting the link for the first time. Here are some repro steps:

1) open a brand new instance of Firefox. visit the jsFiddle below.

2) see nothing

3) open a new tab in Firefox. visit the jsFiddle below.

4) see the result (10 colored squares)

Doing this in Chrome will result in seeing the result at both step 2 and step 4.

https://jsfiddle.net/sk873txv/1/

html

<body>
    <div id="a">
    </div>
</body>

js

$(document).ready(function(){
    var make_canvas = function(i) {
        var $canvas = $('<canvas>').appendTo($('#a'));
        $canvas.attr('width', '100px');
        $canvas.attr('height', '100px');
        var canvas = $canvas[0];
        var ctx = canvas.getContext('2d');
        return ctx;
    };

    var draw = function(ctx) {
       var image = new Image();
       image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkEAIAAACvEN5AAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAABa0lEQVR42u3cMU4CARRF0SeyWl0P7FaxoKbBuRrNOZUJCU7xcv9UvGzb7Xa6btvrddse/f2dT0+Xg77noOd58r9c/tTTPvr08hPPc962z7fBoc7b9mFYHEyxSCgWCcUioVgkDIuEU0hCsUgoFgnFImFYJJxCEopFQrFIKBaJe7Hef/sx+G8Ui4RhkfDyTkKxSCgWCcUiYVgknEISikVCsUgoFgnFIqFYJAyLhFNIQrFIKBYJxSJhWCScQhKKRUKxSCgWCcMi4RSSUCwSikVCsUgoFgnFImFYJJxCEvdi+eE1DqZYJLxjkTAsEk4hCcUioVgkFIuEYpFQLBKGRcIpJKFYJBSLhGKRMCwSTiEJxSKhWCQUi4RhkXAKSSgWCcUioVgkFIuEYpEwLBJOIQnFIqFYJBSLhGGRuJ9CP7zGwRSLhJd3EopFQrFIKBYJwyLhFJJQLBKKRUKxSBgWCaeQhGKRUCwSikVCsUh8ARsPyYz6AmddAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDExLTA0LTA3VDIxOjM2OjAyKzEwOjAwezv9bwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMS0wNC0wN1QyMTozNjowMisxMDowMApmRdMAAAA2dEVYdFBORzpiS0dEAGNodW5rIHdhcyBmb3VuZCAoc2VlIEJhY2tncm91bmQgY29sb3IsIGFib3ZlKbpeXNkAAAAVdEVYdFBORzpJSERSLmJpdF9kZXB0aAAxNqc4FdcAAAAVdEVYdFBORzpJSERSLmNvbG9yX3R5cGUAMgEnYzIAAAAbdEVYdFBORzpJSERSLmludGVybGFjZV9tZXRob2QAMPs7B4wAAAAedEVYdFBORzpJSERSLndpZHRoLGhlaWdodAAxMDAsIDEwMNtVy6kAAAAkdEVYdFBORzpwSFlzAHhfcmVzPTcyLCB5X3Jlcz03MiwgdW5pdHM9MKQw/n0AAAArdEVYdFBORzp0ZXh0ADIgdEVYdC96VFh0L2lUWHQgY2h1bmtzIHdlcmUgZm91bmRcYYD5AAAAAElFTkSuQmCC";
       ctx.drawImage(image, 0, 0);
    };

    for(var i = 0; i < 10; i++)
    {
        draw(make_canvas(i));
    }

});
xoorath
  • 363
  • 1
  • 11
  • I'm not quite sure how to prove this... but I think you might be running into a race condition. Try using the image.onload event to `ctx.drawImage`. It *appears* to work for me but race conditions can be hard to debug sometimes. https://jsfiddle.net/sk873txv/4/ – Norman Breau May 11 '15 at 02:07
  • 1
    Potential duplicate of: http://stackoverflow.com/questions/4776670/should-setting-an-image-src-to-data-url-be-available-immediately also explains why it seems to work as expected in Chrome – Norman Breau May 11 '15 at 02:10

1 Answers1

1

You should wait for the load event to fire on the image, before drawing it to a canvas. Even though the image data is embedded as a data URI, there is no guarantee the image will be rendered and ready to draw the instant you set the src. Waiting for the load event will ensure the image is ready.

Working Example (JSFiddle):

$(document).ready(function(){
    var make_canvas = function(i) {
        var $canvas = $('<canvas>').appendTo($('#a'));
        $canvas.attr('width', '100px');
        $canvas.attr('height', '100px');
        var canvas = $canvas[0];
        var ctx = canvas.getContext('2d');
        return ctx;
    };
    
    var draw = function(ctx) {
       var image = new Image();
       image.onload = function() {
           ctx.drawImage(image, 0, 0);
       };
       image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkEAIAAACvEN5AAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAABa0lEQVR42u3cMU4CARRF0SeyWl0P7FaxoKbBuRrNOZUJCU7xcv9UvGzb7Xa6btvrddse/f2dT0+Xg77noOd58r9c/tTTPvr08hPPc962z7fBoc7b9mFYHEyxSCgWCcUioVgkDIuEU0hCsUgoFgnFImFYJJxCEopFQrFIKBaJe7Hef/sx+G8Ui4RhkfDyTkKxSCgWCcUiYVgknEISikVCsUgoFgnFIqFYJAyLhFNIQrFIKBYJxSJhWCScQhKKRUKxSCgWCcMi4RSSUCwSikVCsUgoFgnFImFYJJxCEvdi+eE1DqZYJLxjkTAsEk4hCcUioVgkFIuEYpFQLBKGRcIpJKFYJBSLhGKRMCwSTiEJxSKhWCQUi4RhkXAKSSgWCcUioVgkFIuEYpEwLBJOIQnFIqFYJBSLhGGRuJ9CP7zGwRSLhJd3EopFQrFIKBYJwyLhFJJQLBKKRUKxSBgWCaeQhGKRUCwSikVCsUh8ARsPyYz6AmddAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDExLTA0LTA3VDIxOjM2OjAyKzEwOjAwezv9bwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMS0wNC0wN1QyMTozNjowMisxMDowMApmRdMAAAA2dEVYdFBORzpiS0dEAGNodW5rIHdhcyBmb3VuZCAoc2VlIEJhY2tncm91bmQgY29sb3IsIGFib3ZlKbpeXNkAAAAVdEVYdFBORzpJSERSLmJpdF9kZXB0aAAxNqc4FdcAAAAVdEVYdFBORzpJSERSLmNvbG9yX3R5cGUAMgEnYzIAAAAbdEVYdFBORzpJSERSLmludGVybGFjZV9tZXRob2QAMPs7B4wAAAAedEVYdFBORzpJSERSLndpZHRoLGhlaWdodAAxMDAsIDEwMNtVy6kAAAAkdEVYdFBORzpwSFlzAHhfcmVzPTcyLCB5X3Jlcz03MiwgdW5pdHM9MKQw/n0AAAArdEVYdFBORzp0ZXh0ADIgdEVYdC96VFh0L2lUWHQgY2h1bmtzIHdlcmUgZm91bmRcYYD5AAAAAElFTkSuQmCC";
    };
    
    for(var i = 0; i < 10; i++)
    {
        draw(make_canvas(i));
    }

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
    <div id="a">
    </div>
</body>
Alexander O'Mara
  • 52,993
  • 16
  • 139
  • 151
  • 1
    Yes, this totally did it for me. For anyone else fixing this issue note that putting the `img.src` assignment after the image.onload is an important step. Kind of obvious I guess, but I missed it on my first go trying this solution ;) – xoorath May 12 '15 at 17:02