Si desidera precaricare le immagini.
Per fare ciò è possibile avviare il caricamento nella parte inferiore della pagina poco prima della chiusura del tag </dody>
.
<script>
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = name; // set the src
images.push(image); // push it onto the image array
});
</script>
Nel codice che utilizza le immagini è sufficiente controllare se sono già stati caricati. Per fare ciò basta controllare l'attributo image complete
.
// draw the first image in the array
if(images[0].complete){ // has it loaded
ctx.drawImage(images[0],0,0); // yes so draw it
}
Nota che complete
non significa caricato. Se hai dimostrato un URL errato o c'è un altro errore, il flag completo sarà ancora true. Completa significa che il browser ha finito di occuparsi dell'immagine. Dovrai aggiungere un evento onload
se c'è la possibilità che le immagini possano fallire.
Gestione degli errori
Se non siete sicuri che l'immagine non verrà caricato si dovrà definire una strategia per affrontare il contenuto mancante. Dovrai rispondere a domande come, La mia app può funzionare senza l'immagine? Ci sono fonti alternative per ottenere l'immagine? C'è un modo per determinare quanto spesso ciò possa accadere? Come faccio a impedire che ciò accada?
Al livello più semplice è possibile bandiera un'immagine come caricata aggiungendo il proprio semaforo per l'oggetto immagine durante la onload
manifestazione
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// function to flag image as loaded
function loaded(){
this.loaded = true;
}
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = name; // set the src
image.onload = loaded; // add the image on load event
images.push(image); // push it onto the image array
});
Poi nel codice che controlla per il semaforo caricato prima di utilizzare l'immagine.
// draw the first image in the array
if(images[0].loaded){ // has it loaded
ctx.drawImage(images[0],0,0); // yes so draw it
}
contenuto critico
Se si dispone di immagini che sono necessari per voi applicazione di funzionare allora si dovrebbe reindirizzare a una pagina di errore se c'è un problema durante il caricamento dell'immagine. Potresti avere diversi server in modo da poter provare anche le diverse fonti prima di rinunciare.
Se è necessario interrompere l'applicazione o provare un URL alternativo, sarà necessario intercettare l'evento di immagine onerror
.
Per semplificare l'utilizzo delle immagini (sicuro al 100% che le immagini vengano caricate durante l'esecuzione dell'app), è necessario avviare le parti che utilizzano le immagini solo quando tutte le immagini sono caricate. Un modo per fare ciò è contare tutte le immagini che vengono caricate e contare il conto alla rovescia mentre le immagini vengono caricate. Quando il contatore raggiunge lo zero, sai che tutte le immagini sono state caricate e puoi quindi chiamarti.
Di seguito vi caricare le immagini, se non riescono cercherà un altro server (fonte) fino a quando non ci sono più opzioni a questo punto si dovrebbe reindirizzamento alla pagina di errore appropriato per informare il cliente che una scimmia ha messo un bastone tra le ruote i lavori. Conta le immagini di caricamento e quando tutte le immagini sono state caricate, l'app verrà avviata, con la certezza che tutto il contenuto dell'immagine è sicuro da usare.
// Server list in order of preferance
var servers = ["https://fakesiteABC.com/", "http://boogusplace.com/", "http://foobarpoo.com.au/"];
// an array of image URLs
var imageNames = ["image1.png", "image2.jpg", ...moreImageNames];
// an array of images
var images = [];
// loading count tracks the number of images that are being loaded
var loadingImageCount = 0;
// function to track loaded images
function loaded(){
loadingImageCount -= 1;
if(loadingImageCount === 0){
// call your application start all images have loaded
appStart();
}
}
// function to deal with error
function loadError(){ // the keyword "this" references the image that generated the event.
if(this.retry === undefined){ // is this the first error
this.retry = 1; // point to the second server
}else{
this.retry += 1; // on each error keep trying servers (locations)
}
// are the any other sources to try?
if(this.retry >= servers.length){ // no 11
// redirect to error page.
return;
}
// try a new server by setting the source and stripping the
// last server name from the previous src URL
this.src = servers[this.retry] + this.src.replace(servers[ this.retry - 1],"");
// now wait for load or error
}
// for each image name create the image and put it into the images array
imageNames.forEach(function(name){
image = new Image(); // create image
image.src = servers[0] + name; // set the src from the first server
image.onload = loaded; // add the image on load event
image.onerror = loadError; // add the image error handler
images.push(image); // push it onto the image array
loadingImageCount += 1; // count the images being loaded.
});
Esistono molte altre strategie per gestire i contenuti mancanti. Questo mostra solo alcuni dei meccanismi utilizzati e non definisce una soluzione perfetta (non ce n'è)
Perché non limitarsi a precaricarli tutti prima di iniziare a utilizzarli? Sembra che la dipendenza da 'ctx.save' e' ctx.restore' ucciderà un approccio uno a uno al caricamento. Sai in anticipo quante immagini ci sono, quindi sai quante volte dovresti aspettarti che l'evento onload di un'immagine venga attivato. – enhzflep
Ciò che dice @enhzflep ... precarica tutte le immagini all'inizio della tua app prima di iniziare ad usarne una qualsiasi. Ci sono dozzine di preloader di immagini su Google - [ecco uno] (http://stackoverflow.com/questions/25235427/two-different-image-onload/25235467#25235467). – markE