Dovrebbe l'impostazione di uno src un'immagine per i dati URL essere disponibile immediatamente?
-
23-10-2019 - |
Domanda
Si consideri il seguente (fragile) codice 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!'); };
The Question (s)
- Qualora la larghezza e l'altezza dell'immagine essere corretto immediatamente?
- Qualora l'tela disegnare subito lavoro?
- Qualora il callback
onload
(set dopo lo src è stato cambiato) essere invocato?
Experimental Test
Ho creato una semplice pagina di prova con codice simile. In Safari miei primi test, sia aprendo la pagina HTML in locale (file:///
url) e il caricamento dal mio assistente, ha mostrato tutto funziona: l'altezza e la larghezza è corretto, la tela disegnano opere, e il onload
anche incendi.
In Firefox v3.6 (OS X), il caricamento della pagina dopo aver lanciato gli spettacoli del browser che l'altezza / larghezza non è corretto immediatamente dopo l'impostazione, drawImage()
fallisce. (Il gestore onload
fa il fuoco, però.) Caricamento nuovamente la pagina, tuttavia, mostra la larghezza / altezza essere corretto subito dopo l'impostazione, e di lavoro drawImage()
. Sembrerebbe che Firefox memorizza nella cache il contenuto della URL di dati come immagine e lo ha immediatamente disponibile quando viene utilizzato nella stessa sessione.
In Chrome v8 (OS X) vedo gli stessi risultati come in Firefox:. L'immagine non è immediatamente disponibile, ma richiede un po 'di tempo per modo asincrono 'carico' dall'URL dati
Oltre alla prova sperimentale di ciò che i browser di cui sopra fa o non funziona, mi piacerebbe davvero link alle specifiche su come questo dovrebbe comportarsi. Finora il mio Google-fu, non è stato all'altezza del compito.
giocare sul sicuro
Per coloro che non capiscono il motivo di cui sopra potrebbe essere pericoloso, sa che si dovrebbe usare le immagini come questo per essere sicuro:
// 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 = '...';
Soluzione
Come nessuno ha ancora trovato tutte le specifiche su come questo è dovrebbe di comportarsi, che dovrà essere soddisfatto di come è ha si comportano. Di seguito sono riportati i risultati dei miei test.
| 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** ------------+-----------------------------+-------------------------------------
In sintesi:
- Non si può dare per scontato che i dati di immagine sarà disponibile subito dopo l'impostazione di un data-URI; è necessario attendere l'evento
onload
. - A causa di IE9, non è possibile impostare il gestore
onload
dopo aver impostato ilsrc
e si aspettano di essere richiamato. - Le raccomandazioni a "andare sul sicuro" (dalla domanda di cui sopra) sono l'unico modo per garantire un comportamento corretto.
Se chiunque può trovare le specifiche parlano di questo, sarò felice di accettare invece la loro risposta.
Altri suggerimenti
Dopo aver dato il controllo al motore di rendering del browser, i rapporti di prova true
in FF 4b9 e cromo 8.0.552.237. Ho modificato queste parti:
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);
Aggiornamento: Sì, ho capito questo 'risposta' è più simile a un commento, ma volevo solo farlo notare. E dopo aver testato ottengo risultati riproducibili:
- senza
setTimeout
, in entrambi i browser ottengofalse
la prima volta che apro la pagina etrue
solo dopo aver colpito F5 . Dopo aver eliminato in modo esplicito la cache Entrambi diconofalse
di nuovo dopo aver ricaricato. - con
setTimeout
il test di larghezza / altezza evualuates sempretrue
.
In entrambi i casi l'immagine non compare la prima volta, solo dopo ricaricare la pagina.