Considérez le code JavaScript (fragile) suivant:
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 (les) question (s)
onload
(défini après la modification du src) doit-il être invoqué? Tests expérimentaux
J'ai créé un page de test simple avec un code similaire. Dans Safari, mes premiers tests, à la fois en ouvrant la page HTML localement (URL file:///
) Et en la chargeant depuis mon serveur, ont montré que tout fonctionnait: la hauteur et la largeur sont correctes, le dessin du canevas fonctionne, et le onload
se déclenche également.
Dans Firefox v3.6 (OS X), le chargement de la page après le lancement du navigateur montre que la hauteur/largeur n'est pas correcte immédiatement après le réglage, drawImage()
échoue. (Le gestionnaire onload
se déclenche cependant.) Le chargement de la page, cependant, montre que la largeur/hauteur est correcte immédiatement après le réglage et que drawImage()
fonctionne. Il semblerait que Firefox met en cache le contenu de l'URL de données sous forme d'image et qu'il soit disponible immédiatement 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 n'est pas disponible immédiatement, mais prend un certain temps pour se charger de manière asynchrone à partir de l'URL de données.
En plus de la preuve expérimentale de ce que les navigateurs ci-dessus fonctionnent ou ne fonctionnent pas, j'aimerais vraiment des liens vers des spécifications sur la façon dont cela doit se comporter. Jusqu'à présent, mon Google-fu n'a pas été à la hauteur.
Jouer en toute sécurité
Pour ceux qui ne comprennent pas pourquoi ce qui précède pourrait être dangereux, sachez que vous devez utiliser des images comme celle-ci pour être en sécurité:
// 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 = '...';
Comme personne n'a encore trouvé de spécifications sur la façon dont cela ( est supposé se comporter, nous devrons être satisfaits de la façon dont cela se comporte . Voici les résultats de mes tests.
| les données d'image sont-elles utilisables à droite | effectue le rappel onload défini après src | après avoir défini src? | est changé toujours invoqué? ------------ + -------------------------- --- + ------------------------------------- Safari 5 | oui | oui ------------ + ----------------------------- + - ------------------------------------ Chrome 8 | ** non ** (chargement de la 1ère page), mais | oui FireFox 3.6 | oui par la suite (mis en cache) | ------------ + ----------------------------- + - ----------------------------------- IE8 | oui (limite de données de 32 Ko) | oui ------------ + ----------------------------- + - ------------------------------------ IE9b | oui | ** non ** ------------ + --------------------------- - + -------------------------------------
En résumé:
onload
.onload
après avoir défini le src
et vous attendre à ce qu'il soit appelé.Si quelqu'un peut trouver des spécifications en discutant, j'accepterai volontiers sa réponse à la place.
Après avoir redonné le contrôle au moteur de rendu du navigateur, le test rapporte true
dans FF 4b9 et Chromium 8.0.552.237. J'ai 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);
pdate: Oui, je comprends que cette "réponse" ressemble plus à un commentaire, mais je voulais juste le souligner. Et après les tests, j'obtiens des résultats reproductibles:
setTimeout
, dans les deux navigateurs j'obtiens false
la première fois que j'ouvre la page et true
seulement après avoir appuyé F5. Après avoir effacé explicitement le cache, les deux disent à nouveau false
après le rechargement.setTimeout
le test largeur/hauteur s'évalue toujours à true
.Dans les deux cas, l'image n'apparaît pas la première fois, uniquement après le rechargement de la page.