2008-11-04 6 views
79

Sto scrivendo alcuni Javascript per ridimensionare l'immagine grande per adattarla alla finestra del browser dell'utente. (Non controllo la dimensione delle immagini di origine, purtroppo.)Come posso determinare se un'immagine è stata caricata, usando Javascript/jQuery?

Quindi qualcosa di simile sarebbe nel codice HTML:

<img id="photo" 
    src="a_really_big_file.jpg" 
    alt="this is some alt text" 
    title="this is some title text" /> 

C'è un modo per me per determinare se l'immagine src in un tag img è stato scaricato?

Ho bisogno di questo perché sto incontrando un problema se $(document).ready() viene eseguito prima che il browser abbia caricato l'immagine. $("#photo").width() e $("#photo").height() restituiranno la dimensione del segnaposto (il testo alt). Nel mio caso questo è qualcosa come 134 x 20.

In questo momento sto solo controllando se l'altezza della foto è inferiore a 150 e supponendo che, in tal caso, si tratti solo di testo alternativo. Ma questo è piuttosto un trucco, e si interromperebbe se una foto è alta meno di 150 pixel (non è probabile nel mio caso particolare), o se il testo alt è più alto di 150 pixel (potrebbe accadere su una piccola finestra del browser) .


Edit: per chi vuole vedere il codice:

$(function() 
{ 
    var REAL_WIDTH = $("#photo").width(); 
    var REAL_HEIGHT = $("#photo").height(); 

    $(window).resize(adjust_photo_size); 
    adjust_photo_size(); 

    function adjust_photo_size() 
    { 
    if(REAL_HEIGHT < 150) 
    { 
     REAL_WIDTH = $("#photo").width(); 
     REAL_HEIGHT = $("#photo").height(); 
     if(REAL_HEIGHT < 150) 
     { 
     //image not loaded.. try again in a quarter-second 
     setTimeout(adjust_photo_size, 250); 
     return; 
     } 
    } 

    var new_width = . . . ; 
    var new_height = . . . ; 

    $("#photo").width(Math.round(new_width)); 
    $("#photo").height(Math.round(new_height)); 
    } 

}); 

Aggiornamento: Grazie per i suggerimenti. Esiste il rischio che l'evento non venga attivato se imposto una richiamata per l'evento $("#photo").load, quindi ho definito un evento onLoad direttamente sul tag immagine. Per la cronaca, ecco il codice ho finito per andare con:

<img id="photo" 
    onload="photoLoaded();" 
    src="a_really_big_file.jpg" 
    alt="this is some alt text" 
    title="this is some title text" /> 

Poi in Javascript:

//This must be outside $() because it may get called first 
var isPhotoLoaded = false; 
function photoLoaded() 
{ 
    isPhotoLoaded = true; 
} 

$(function() 
{ 
    //Hides scrollbars, so we can resize properly. Set with JS instead of 
    // CSS so that page doesn't break with JS disabled. 
    $("body").css("overflow", "hidden"); 

    var REAL_WIDTH = -1; 
    var REAL_HEIGHT = -1; 

    $(window).resize(adjust_photo_size); 
    adjust_photo_size(); 

    function adjust_photo_size() 
    { 
    if(!isPhotoLoaded) 
    { 
     //image not loaded.. try again in a quarter-second 
     setTimeout(adjust_photo_size, 250); 
     return; 
    } 
    else if(REAL_WIDTH < 0) 
    { 
     //first time in this function since photo loaded 
     REAL_WIDTH = $("#photo").width(); 
     REAL_HEIGHT = $("#photo").height(); 
    } 

    var new_width = . . . ; 
    var new_height = . . . ; 

    $("#photo").width(Math.round(new_width)); 
    $("#photo").height(Math.round(new_height)); 
    } 

}); 
+1

Questo è così vecchio e hai già accettato una risposta, quindi mi limiterò a commentare qui. Perché non puoi usare il plugin jQuery 'onImagesLoad'? Inoltre, jQuery o no, cosa c'è di sbagliato nell'impostare 'max-width' e' max-height' nello stile dell'immagine con Javascript? Evita quindi TUTTO il codice che hai bisogno di scrivere impostando la larghezza/altezza massima alla dimensione della larghezza/altezza della finestra. – jonwd7

+0

@ jon.wd7: non ho familiarità con quel plug-in e potrebbe non essere stato pubblicato nel 2008. come per max-width e max-height, due cose: 1) non sono supportate in IE (beh non sono sicuro di IE 8); 2) se la vista cambia dimensione (la finestra viene ridimensionata, ecc.) Allora avrei ancora bisogno di javascript per modificare la larghezza massima/altezza massima (anche se non posso se ho usato "100%" piuttosto che una misurazione pixel) – Kip

+0

È decisamente supportato in IE7 e IE8, secondo quirksmode.org. Quindi non sono sicuro del tuo problema. Personalmente non supporto IE6 per piccole cose come questa, quindi quello che vedranno è la stessa cosa che un utente senza JS abilitato vedrebbe. E ovviamente dovresti reimpostare 'max-width' e' max-height' sul ridimensionamento. Ma è un compito abbastanza facile, un one-liner che usa infatti ".resize()". – jonwd7

risposta

29

O aggiungere un listener di eventi, o di avere l'immagine stessa annunciare con onload. Quindi scopri le dimensioni da lì.

<img id="photo" 
    onload='loaded(this.id)' 
    src="a_really_big_file.jpg" 
    alt="this is some alt text" 
    title="this is some title text" /> 
+0

Secondo le specifiche, onload è solo un evento per gli elementi body e frameset; Detto questo, credo che questo funziona in IE, ma non so che funziona in qualsiasi altro browser o che si tratta di qualcosa che si può assumere ... Stavo guardando in questo un paio di settimane fa ... –

+0

I l'ho testato in IE6, IE7, FF3, Opera9, Safair (Windows Beta) e Chrome (Windows Beta). – Kip

+8

Il comportamento e il contenuto della messaggistica sono sconsigliati. Gli eventi dovrebbero essere applicati usando Javascript, non in HTML. – dionyziz

3

Prova qualcosa di simile:

$("#photo").load(function() { 
    alert("Hello from Image"); 
}); 
+4

Grazie. Tuttavia, esiste la possibilità che l'immagine sia già stata caricata prima che ciò accada, nel qual caso l'evento di caricamento non verrebbe attivato. – Kip

+0

Che ne dici di un tag script che imposta questo evento subito dopo il tag immagine? La ragione per usare pronto è assicurarsi che l'intero documento sia caricato, che in questo caso non è necessario, giusto? –

5

Vuoi fare quello che ha detto Allain, tuttavia essere consapevoli del fatto che a volte i carichi di immagini, prima dom pronto, il che significa che il tuo gestore del carico non scatta mai. Il modo migliore è quello di fare come dice Allain, ma impostare la src dell'immagine con javascript dopo aver allegato il load hander. In questo modo puoi garantire che spari.

In termini di accessibilità, il sito funzionerà ancora per le persone senza javascript? Puoi dare al tag img il corretto src, allegare il tuo gestore dom pronto a far girare il tuo js: cancella l'immagine src (dagli un fisso e l'altezza con css per evitare lo sfarfallio della pagina), quindi imposta il gestore di caricamento img, quindi resettare lo src al file corretto. In questo modo si coprono tutte le basi :)

+0

Il sito funziona ancora per le persone senza Javascript, devono solo scorrere per vedere tutta l'immagine. – Kip

2

Qualche commento su questo?

...

doShow = function(){ 
    if($('#img_id').attr('complete')){ 
    alert('Image is loaded!'); 
    } else { 
    window.setTimeout('doShow()',100); 
    } 
}; 

$('#img_id').attr('src','image.jpg'); 

doShow(); 

...

Sembra come funziona ovunque ...

+0

Non funziona in Chrome 32.0.1700.107. – Nate

9

La risposta giusta, è quello di utilizzare event.special.load

E 'possibile che l'evento carico non verrà attivato se l'immagine viene caricata dalla cache del browser. Per tenere conto di questa possibilità, possiamo utilizzare un evento di carico speciale che si attiva immediatamente se l'immagine è pronta. event.special.load è attualmente disponibile come plug-in.

Per la documentazione sul .load()

+2

Stavo per aggiungere una risposta con un suggerimento come questo, felice di aver visto questa risposta prima di codificarla. Fondamentalmente, i gestori devono prima controllare se l'immagine viene caricata prima di impostare il gestore. Se è già caricato, attiva immediatamente la richiamata. È ciò che '$. Stavo per suggerire di controllare la larghezza, ma questo ha i suoi problemi, mi piace molto questa soluzione. –

14

Utilizzando il jquery data store è possibile definire uno stato di 'carico'.

<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" /> 

poi altrove si può fare:

if ($('#myimage').data('loaded')) { 
    // loaded, so do stuff 
} 
+2

Usa 'jQuery (this)' invece di '$ (this)' per una migliore compatibilità con altre librerie (jquery non possiede $), specialmente quando hai JavaScript in html. –

1

Ho appena creato una funzione di jQuery per caricare un'immagine utilizzando jQuerys Deferred Object che lo rende molto facile reagire al carico/evento di errore:

$.fn.extend({ 
    loadImg: function(url, timeout) { 
     // init deferred object 
     var defer = $.Deferred(), 
      $img = this, 
      img = $img.get(0), 
      timer = null; 

     // define load and error events BEFORE setting the src 
     // otherwise IE might fire the event before listening to it 
     $img.load(function(e) { 
      var that = this; 
      // defer this check in order to let IE catch the right image size 
      window.setTimeout(function() { 
       // make sure the width and height are > 0 
       ((that.width > 0 && that.height > 0) ? 
        defer.resolveWith : 
        defer.rejectWith)($img); 
      }, 1); 
     }).error(function(e) { 
      defer.rejectWith($img); 
     }); 

     // start loading the image 
     img.src = url; 

     // check if it's already in the cache 
     if (img.complete) { 
      defer.resolveWith($img); 
     } else if (0 !== timeout) { 
      // add a timeout, by default 15 seconds 
      timer = window.setTimeout(function() { 
       defer.rejectWith($img); 
      }, timeout || 15000); 
     } 

     // return the promise of the deferred object 
     return defer.promise().always(function() { 
      // stop the timeout timer 
      window.clearTimeout(timer); 
      timer = null; 
      // unbind the load and error event 
      this.off("load error"); 
     }); 
    } 
}); 

Utilizzo:

var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png') 
.done(function() { 
    alert('image loaded'); 
    $('body').append(this); 
}).fail(function(){ 
    alert('image failed'); 
}); 

vederlo lavorare a: http://jsfiddle.net/roberkules/AdWZj/

+0

Sembra meraviglioso. Puoi dare un esempio esatto di quando il tuo codice è preferibile a img.onload e img.onerror? Il tuo codice ha solo lo scopo di gestire le apparenti carenze della gestione degli errori di jQuery. Mi hanno appena informato: l'errore non si attiva in IE se non ci sono estensioni di file? – mplungjan

+0

idea interessante. quindi sapere quando l'immagine è facile. Ma cosa accadrebbe se non fosse possibile caricare l'immagine. Stavo cercando un modo per sapere se il caricamento dell'immagine è fallito. e mi hai dato l'idea del timeout scaricandolo. +1 per quello – oak

+1

@oak il timeout dovrebbe essere solo un fallback. la maggior parte dei browser dovrebbe lanciare un evento 'error' che è gestito da' .error (function (e) {defer.rejectWith ($ img);}) '. Se guardi il jsFiddle vedrai che il testo 'http://www.google.com/abc.png non trovato' viene mostrato immediatamente nel riquadro dei risultati (non in attesa di un timeout, perché l'evento di errore è stato avviato) – roberkules

1

controlla questa funzione se l'immagine viene caricata sulla base avente dimensioni misurabili. Questa tecnica è utile se lo script è in esecuzione dopo che alcune delle immagini sono già state caricate.

imageLoaded = function(node) { 
    var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth; 
    var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight; 
    return w+h > 0 ? true : false; 
}; 
+0

Ho scoperto che questa soluzione potrebbe richiedere che non vi siano margini o spaziatura nell'immagine e che venga fornito il testo alternativo di una stringa vuota. Nella maggior parte dei casi però, funziona come previsto. Fallirà solo se la dimensione dell'immagine scaricata è maggiore di zero. –

2

C'è un plugin jQuery chiamato "imagesLoaded", che fornisce un metodo compatibile cross-browser per controllare se un'immagine (s) di un elemento sono stati caricati.

sito: https://github.com/desandro/imagesloaded/

di utilizzo per un contenitore che ha molte immagini all'interno:

$('container').imagesLoaded(function(){ 
console.log("I loaded!"); 
}) 

Il plugin è grande:

  1. opere per il controllo di un contenitore con molte immagini all'interno
  2. funziona per controllare un img per vedere se ha caricato
4

Come per uno dei recenti commenti alla tua domanda iniziale

$(function() { 

    $(window).resize(adjust_photo_size); 
    adjust_photo_size(); 

    function adjust_photo_size() { 
    if (!$("#photo").get(0).complete) { 
     $("#photo").load(function() { 
      adjust_photo_size(); 
     }); 
    } else { 
     ... 
    } 
}); 

Attenzione Questa risposta potrebbe causare una grave ciclo in IE8 e più basso, perché img.complete non sempre è impostato correttamente dal browser. Se devi supportare ie8, usa una bandiera per ricordare che l'immagine è stata caricata.

+0

Tienilo.Questa risposta potrebbe causare un loop serio in ie8 e inferiore, perché img.complete non è sempre impostato correttamente dal browser. Se devi supportare ie8, usa una bandiera per ricordare che l'immagine è stata caricata. – commonpike

1

ho trovato questo ha lavorato per me

document.querySelector("img").addEventListener("load", function() { alert('onload!'); }); 

Merito va totalmente a Frank Schwieterman, che ha commentato in risposta accettata. Ho dovuto metterlo qui, è troppo prezioso ...

0

Abbiamo sviluppato una pagina in cui è stato caricato un numero di immagini e quindi eseguito altre funzioni solo dopo che l'immagine è stata caricata. Era un sito occupato che generava molto traffico. Sembra che il seguente semplice script ha lavorato su praticamente tutti i browser:

$(elem).onload = function() { 
    doSomething(); 
} 

ma questo è un potenziale problema PER IE9!

L'UNICO browser su cui abbiamo segnalato problemi è IE9. Non siamo sorpresi? Sembra che il modo migliore per risolvere il problema è di non assegnare uno src all'immagine fino a dopo la funzione onload è stato definito, in questo modo:

$(elem).onload = function() { 
    doSomething(); 
} 
$(elem).attr('src','theimage.png'); 

sembra che IE 9 talvolta non gettare il onload evento per qualunque motivo. Altre soluzioni su questa pagina (come quella di Evan Carroll, ad esempio) non funzionavano ancora. Logicamente, quello ha verificato se lo stato di caricamento era già riuscito e ha attivato la funzione e se non lo era, quindi imposta il gestore onload, ma anche quando lo fai dimostriamo in testing che l'immagine potrebbe caricare tra quelle due linee di js quindi apparendo non caricato sulla prima riga e quindi caricando prima che sia impostato il gestore onload.

Abbiamo trovato che il modo migliore per ottenere quello che vuoi è non definire lo src dell'immagine finché non hai impostato l'innesco dell'evento onload.

Abbiamo appena smesso di supportare IE8 quindi non posso parlare per le versioni precedenti a IE9, altrimenti, tra tutti gli altri browser utilizzati sul sito - IE10 e 11 nonché Firefox, Chrome, Opera , Safari e qualsiasi altra cosa utilizzassero i browser dei dispositivi mobili: impostare lo prima di assegnare il gestore onload non era nemmeno un problema.