Dovrebbe l'impostazione di uno src un'immagine per i dati URL essere disponibile immediatamente?

StackOverflow https://stackoverflow.com/questions/4776670

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 = '...';
È stato utile?

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 il src 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 ottengo false la prima volta che apro la pagina e true solo dopo aver colpito F5 . Dopo aver eliminato in modo esplicito la cache Entrambi dicono false di nuovo dopo aver ricaricato.
  • con setTimeout il test di larghezza / altezza evualuates sempre true.

In entrambi i casi l'immagine non compare la prima volta, solo dopo ricaricare la pagina.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top