Question

Considérez ce qui suit (fragile) code JavaScript:

var img = new Image;
img.src = "data:image/png;base64,..."; // Assume valid data

// Danger(?) Attempting to use image immediately after setting src
console.log( img.width, img.height );
someCanvasContext.drawImage( img, 0, 0 );

// Danger(?) Setting onload after setting src
img.onload = function(){ console.log('I ran!'); };

La question (s)

  • Au cas où la largeur de l'image et la hauteur est correcte immédiatement?
  • Au cas où la toile tirer immédiatement le travail?
  • Au cas où le rappel onload (jeu après la src a été changé) être invoquée?

Tests expérimentaux J'ai créé une page de test simple avec un code similaire. Dans Safari mes premiers essais, à la fois en ouvrant la page HTML localement (url file:///) et le charger de mon serveur, tout montré travaillent: la hauteur et la largeur est correcte, la toile dessiner des œuvres, et la onload également les incendies.

Dans Firefox v3.6 (OS X), chargement de la page après le lancement des spectacles de navigateur que la hauteur / largeur n'est pas correcte immédiatement après le réglage, drawImage() échoue. (Le gestionnaire de onload fait feu, cependant.) Chargement de la page à nouveau, cependant, montre la largeur / hauteur étant correcte immédiatement après le réglage, et le travail de drawImage(). Il semblerait que Firefox met en cache le contenu de l'URL de données sous forme d'image et a immédiatement disponible lorsqu'il est utilisé dans la même session.

Dans Chrome v8 (OS X) Je vois les mêmes résultats que dans Firefox. L'image est disponible immédiatement, mais prend un certain temps de manière asynchrone « charge » de l'URL de données

En plus de la preuve expérimentale de ce que les navigateurs les ci-dessus ou ne fonctionne pas, j'aimerais vraiment des liens vers les spécifications sur la façon dont cela est censé se comporter. Jusqu'à présent, mon Google-fu n'a pas été à la hauteur de la tâche.

It Safe Jouer Pour ceux qui ne comprennent pas pourquoi ce qui précède peut être dangereux, sachez que vous devez utiliser des images comme celui-ci pour être sûr:

// First create/find the image
var img = new Image;

// Then, set the onload handler
img.onload = function(){
  // Use the for-sure-loaded img here
};

// THEN, set the src
img.src = '...';
Était-ce utile?

La solution

Comme personne n'a encore trouvé de spécifications sur la façon dont cela est supposé à se comporter, nous devrons être satisfait de la façon dont il Finalité se tenir. Voici les résultats de mes tests.

            | is image data usable right  | does onload callback set after src
            |     after setting src?      |   is changed still get invoked?
------------+-----------------------------+-------------------------------------
Safari  5   |             yes             |                  yes                
------------+-----------------------------+-------------------------------------
Chrome  8   | **no** (1st page load), but |                  yes                
FireFox 3.6 |  yes thereafter (cached)    |                                     
------------+-----------------------------+-------------------------------------
IE8         |    yes (32kB data limit)    |                  yes         
------------+-----------------------------+-------------------------------------
IE9b        |             yes             |                 **no**              
------------+-----------------------------+-------------------------------------

En résumé:

  • Vous ne pouvez pas supposer que les données d'image sera disponible juste après la mise en une uri données; vous devez attendre l'événement onload.
  • En raison de IE9, vous ne pouvez pas définir le gestionnaire de onload après avoir réglé le src et attendre qu'il soit invoqué.
  • Les recommandations contenues dans "En toute sécurité" (de la question ci-dessus) sont la seule façon d'assurer un comportement correct.

Si quelqu'un peut trouver les spécifications discuter, je serai heureux d'accepter leur réponse à la place.

Autres conseils

Après redonnant de commande au moteur de rendu du navigateur, les rapports d'essais true dans FF 4B9 et Chrome 8.0.552.237. Je modifié ces parties:

img.onload = function(){   // put this above img.src = …
    document.getElementById('onload').innerHTML = 'yes';
};
img.src = img_src;
…
window.setTimeout(function () {   // put this inside setTimeout
    document.getElementById('wh').innerHTML = (img.height==img.width) && (img.height==128);
}, 0);

Mise à jour: Oui, je comprends cette « réponse » est plus comme un commentaire, mais je voulais juste le signaler. Et après avoir testé j'obtenir des résultats reproductibles:

  • sans setTimeout, dans les deux navigateurs que je reçois false la première fois que j'ouvre la page et true seulement après avoir frappé F5 . Après avoir supprimé explicitement le cache à la fois de false de dire à nouveau après le rechargement.
  • avec setTimeout test largeur / hauteur evualuates toujours true.

Dans les deux cas, l'image ne montre pas la première fois, seulement après rechargement de la page.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top