0

Here my code in my head section:

   <script src="jquery-1.10.1.min.js"></script>
   <script src="metro.js"></script>
   <script src="draw.js"></script>
   <script>
       $(document).ready(function() {
           var im = $('<img />')
               .attr({id: 'metro', src:'metro.png'})
               .appendTo($('body'))
               .hide()
               .on('load', function() {
                   okIm = true;
                   drawIfOk();
               });
           var bg = $('<img />')
               .attr({id: 'back', src:'back.png'})
               .appendTo($('body'))
               .hide()
               .on('load', function() {
                   okBg = true;
                   drawIfOk();
               });
       });
   </script>

This code should download dynamically 2 images and in the drawIfOk(); function, i test if both images are downloaded. If so, then I try to create canvas based on the width & height of the image, like this:

function drawIfOk() {
    if (!okIm) {
        return;
    }
    if (!okBg) {
        return;
    }

    initTest();
}

Simple eh?

Now the initTest(); function is very simple:

function initTest() {
    gImgMetro = $('#metro')[0];
    var bg = $('#back')[0];

    /* Création du canvas */
    gImgCanvas = $('<canvas />').attr({
        width: bg.width,
        height: bg.height
    })[0];
    gImgCtx = gImgCanvas.getContext('2d');
    if(!gImgCtx) {
        displayError("Impossible de récupérer le context du canvas");
        return;
    }
}

Then IE gives me an error because bg.width and bg.height are 0 whereas it works on Safari, Chrome, Firefox and Maxthon! [Trying not to grumble about IE]

How to circumvent this?

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213

2 Answers2

1

The MSIE problem appears to be related to its poor handling of hidden image elements.

Image elements that have been added to the DOM and then explicitly hidden cannot have their dimensions read, but it would appear that a stand-alone Image object does not have this problem.

There are also far better ways of handling the image loading synchronisation - the code below replicates most of your set up code using jQuery's "deferred objects":

function loadImage(id, url) {
    return $.Deferred(function(def) {
       var img = new Image();
       $(img).one('load', function() {
          def.resolve(img);
       }).hide().appendTo(document.body);
       img.id = id;
       img.src = url;
    }).promise();
}

var im = loadImage('metro', 'metro.png');
var bg = loadImage('back', 'back.png');

With usage:

$.when(im, bg).done(initTest);

You can then access the two images within initTest as they will be passed as parameters, and only then put them into the DOM

function initTest(gImgMetro, bg) {
    // bg.width *should* be available here
    ...

    // add to the DOM
    $('body').append(gImgMetro, bg);
}
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • This is a very nice answer. I'll modify my code accordingly, but FYI, putting `onLoad` before setting `src` doesn't change anything. The workaround seems to be here http://stackoverflow.com/questions/4472086/getting-image-width-on-image-load-fails-on-ie but all the solutions are ugly – Olivier Pons Jun 29 '13 at 20:53
  • @OlivierPons this article suggests you can just create an `Image` element off-screen with the same `.src` and read its `width` and `height` properties - http://www.jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie/ – Alnitak Jun 29 '13 at 20:58
  • @OlivierPons alternatively, don't hide the images and add them to the DOM straight away in `loadImage` - hold the DOM addition over into the `initTest` function. The way I've written the code above you'll have references to the images as parameters, so they don't need to be in the DOM for you to use them. – Alnitak Jun 29 '13 at 21:07
  • OMG! Ow Myw Gowd. It seems it works (I had to reboot under Windows). May I ask you if it works for you too here: http://olivierpons.fr/download/metro/ ? (Select something in the combo then wait (you could use this as a benchmark and compare code between IE, Firefox, Safari and Chrome... the lastest one is the big winner by far (or maybe my code is not optimized enough...))) – Olivier Pons Jun 29 '13 at 21:31
  • @OlivierPons I don't have a windows system handy – Alnitak Jun 29 '13 at 22:57
  • Well. This works in IE9 but not the first time. You have to refresh the page to make it work. What is incredibly strange is that I create dynamically a combo box and in IE9 this combo box appears empty. I dont get what's happening at all. If you have any idea.. – Olivier Pons Jul 02 '13 at 15:19
0

I did it once like this

//set image's src here

var $pomImg = new Image();
$pomImg.src = $src;
$pomImg.onload = function(){
    initTest(); //do something here (maybe load second image the same way)
}
if($pomImg.complete == true){
    initTest(); //do something here
}
mkutyba
  • 1,417
  • 1
  • 10
  • 26