Maneira oficial de solicitar ao jQuery wait que todas as imagens sejam carregadas antes de executar algo

641

No jQuery, quando você faz isso:

$(function() {
   alert("DOM is loaded, but images not necessarily all loaded");
});

Ele aguarda o DOM carregar e executa seu código. Se todas as imagens não forem carregadas, ele ainda executará o código. Obviamente, é isso que queremos se estiver inicializando qualquer coisa do DOM, como mostrar ou ocultar elementos ou anexar eventos.

Digamos que eu queira alguma animação e não a execute até que todas as imagens sejam carregadas. Existe uma maneira oficial no jQuery de fazer isso?

A melhor maneira que tenho é usar <body onload="finished()">, mas realmente não quero fazer isso, a menos que seja necessário.

Nota: Há um bug no jQuery 1.3.1 no Internet Explorer que realmente espera que todas as imagens sejam carregadas antes de executar o código dentro $function() { }. Portanto, se você estiver usando essa plataforma, obterá o comportamento que estou procurando, em vez do comportamento correto descrito acima.

Simon_Weaver
fonte
3
não $("img").load()funciona?
21412 Lucas
1
Eu acho que vale a pena mencionar que, se você definir os atributos das dimensões, poderá executar com segurança algum código na função ready que depende dessas dimensões. Com o php, você pode acessá- los com php.net/manual/en/function.getimagesize.php no upload para armazená-los em db ou antes da saída para o navegador.
Alqin
se você quiser algo que esteja fazendo um trabalho incrível, verifique a biblioteca javascript imagesloaded extremamente boa e popular mencionada nesta resposta abaixo stackoverflow.com/a/26458347/759452
Adrien Seja
"Aqui vim para encontrar qualquer coisa, exceto uma maneira oficial."
Léon Pelletier

Respostas:

1035

Com o jQuery, você costuma $(document).ready()executar algo quando o DOM é carregado e $(window).on("load", handler)executar algo quando todas as outras coisas também são carregadas, como as imagens.

A diferença pode ser vista no seguinte arquivo HTML completo, desde que você tenha jollyrogerarquivos JPEG (ou outros adequados):

<html>
    <head>
        <script src="jquery-1.7.1.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                alert ("done");
            });
        </script>
    </head><body>
        Hello
        <img src="jollyroger00.jpg">
        <img src="jollyroger01.jpg">
        // : 100 copies of this
        <img src="jollyroger99.jpg">
    </body>
</html>

Com isso, a caixa de alerta aparece antes do carregamento das imagens, porque o DOM está pronto nesse momento. Se você mudar:

$(document).ready(function() {

para dentro:

$(window).on("load", function() {

a caixa de alerta não aparecerá até depois que as imagens forem carregadas.

Portanto, para esperar até que a página inteira esteja pronta, você pode usar algo como:

$(window).on("load", function() {
    // weave your magic here.
});
paxdiablo
fonte
32
cheira testa +1 esqueci totalmente isso. $ (window) .load () não será acionado até que as imagens sejam concluídas.
21411 Paolo Bergantino
10
Eu fiz o mesmo. Mesmo, leia uma resposta sem saber que era eu e ainda não entendendo.
Rimian 17/09/10
24
Apenas uma observação - isso parece não funcionar no Chromium (e presumo que o Chrome). O evento $ (window) .ready parece disparar o mesmo que $ (document) .ready - antes das imagens serem concluídas.
Nathan Crause
24
mas é $ (window) .load (function ())
TJ-
3
@KyorCode Você tem certeza de que não é apenas porque as imagens no IE foram armazenadas em cache? Se isso acontecer, eles não acionarão um evento "load". Este artigo ajuda a contornar esse problema.
Jamie Barker
157

Eu escrevi um plugin que pode acionar retornos de chamada quando as imagens são carregadas em elementos ou acionar uma vez por imagem carregada.

É semelhante a $(window).load(function() { .. }), exceto que permite definir qualquer seletor para verificar. Se você deseja apenas saber quando todas as imagens #content(por exemplo) foram carregadas, este é o plugin para você.

Ele também suporta o carregamento de imagens referenciadas na CSS, tais como background-image, list-style-image, etc.

plugin jQuery waitForImages

Exemplo de uso

$('selector').waitForImages(function() {
    alert('All images are loaded.');
});

Exemplo em jsFiddle .

Mais documentação está disponível na página do GitHub.

alex
fonte
1
Obrigado!! $ .load () não estava funcionando para mim, mas isso funciona perfeitamente.
Fraxtil
Eu uso o Chrome versão 22.0.1229.94 e esse plug-in e tentei ler os desvios das imagens carregadas no waitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...});no entanto, offset.top ainda é zero. Por quê?
basZero
1
@basZero Difícil de dizer sem mais contexto. Por favor, levante um problema na página Problemas .
alex
Não está funcionando para mim quando as imagens são capturadas. Any1 tem uma solução alternativa para isso?
Mandeep Jain
2
É basicamente analógico para imagesLoaded, mas também funciona com srcsets. Exatamente o que eu estava procurando! Ótimo plugin!
Fabian Schöner
48

$(window).load()funcionará apenas na primeira vez que a página for carregada. Se você estiver fazendo coisas dinâmicas (exemplo: clique no botão, aguarde o carregamento de novas imagens), isso não funcionará. Para conseguir isso, você pode usar meu plugin:

Demo

Baixar

/**
 *  Plugin which is applied on a list of img objects and calls
 *  the specified callback function, only when all of them are loaded (or errored).
 *  @author:  H. Yankov (hristo.yankov at gmail dot com)
 *  @version: 1.0.0 (Feb/22/2010)
 *  http://yankov.us
 */

(function($) {
$.fn.batchImageLoad = function(options) {
    var images = $(this);
    var originalTotalImagesCount = images.size();
    var totalImagesCount = originalTotalImagesCount;
    var elementsLoaded = 0;

    // Init
    $.fn.batchImageLoad.defaults = {
        loadingCompleteCallback: null, 
        imageLoadedCallback: null
    }
    var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);

    // Start
    images.each(function() {
        // The image has already been loaded (cached)
        if ($(this)[0].complete) {
            totalImagesCount--;
            if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
        // The image is loading, so attach the listener
        } else {
            $(this).load(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // An image has been loaded
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
            $(this).error(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // The image has errored
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
        }
    });

    // There are no unloaded images
    if (totalImagesCount <= 0)
        if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
};
})(jQuery);
Roko C. Buljan
fonte
apenas no caso de alguém precisar de um exemplo de uso para o plugin BatchImagesLoad: yankov.us/batchImageLoad
Jonathan Marzullo
1
Não quero desrespeitar, mas não se pode confiar "apenas" na sua palavra em relação à confiabilidade do seu plugin. Como mencionado na Yevgeniy Afanasyevresposta , o imagesLoaded faz um trabalho muito melhor nisso e cobre o caso de uso que você mencionou junto com muitos outros casos de canto (consulte os problemas resolvidos do github) .
Adrien Seja
19

Para aqueles que desejam ser notificados da conclusão do download de uma única imagem solicitada após o $(window).loaddisparo, você pode usar o loadevento do elemento de imagem .

por exemplo:

// create a dialog box with an embedded image
var $dialog = $("<div><img src='" + img_url + "' /></div>");

// get the image element (as a jQuery object)
var $imgElement = $dialog.find("img");

// wait for the image to load 
$imgElement.load(function() {
    alert("The image has loaded; width: " + $imgElement.width() + "px");
});
Dan Passaro
fonte
13

Até agora, nenhuma das respostas deu a que parece ser a solução mais simples.

$('#image_id').load(
  function () {
    //code here
});
Coz
fonte
O que é legal nisso é que você pode acioná-lo para imagens individuais assim que elas forem carregadas.
Cat Top
6

Eu recomendaria usar a imagesLoaded.jsbiblioteca javascript.

Por que não usar jQuery $(window).load()?

Conforme solicitado em /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

É uma questão de escopo. imagesLoaded permite direcionar um conjunto de imagens, enquanto $(window).load()direciona todos os ativos - incluindo todas as imagens, objetos, arquivos .js e .css e até iframes. Provavelmente, o imagesLoaded será acionado mais cedo do que $(window).load()porque está segmentando um conjunto menor de ativos.

Outras boas razões para usar imagesloaded

  • oficialmente suportado pelo IE8 +
  • licença: MIT License
  • dependências: nenhuma
  • peso (compactado e compactado): 7kb compactado (leve!)
  • construtor de downloads (ajuda a reduzir o peso): sem necessidade, já pequeno
  • no Github: SIM
  • comunidade e colaboradores: muito grandes, mais de 4000 membros, embora apenas 13 colaboradores
  • histórico e contribuições: estável como relativamente antigo (desde 2010), mas ainda ativo

Recursos

Adrien Be
fonte
4

Com jQuery eu venho com isso ...

$(function() {
    var $img = $('img'),
        totalImg = $img.length;

    var waitImgDone = function() {
        totalImg--;
        if (!totalImg) alert("Images loaded!");
    };

    $('img').each(function() {
        $(this)
            .load(waitImgDone)
            .error(waitImgDone);
    });
});

Demonstração: http://jsfiddle.net/molokoloco/NWjDb/

molokoloco
fonte
Descobri que isso não funcionará corretamente se o navegador retornar a resposta 304 Não Mofificada para a imagem, o que significa que a imagem está em cache.
precisa saber é o seguinte
1

Use imagesLoaded PACKAGED v3.1.8 (6.8 Kb quando minimizado). É relativamente antigo (desde 2010), mas ainda está ativo.

Você pode encontrá-lo no github: https://github.com/desandro/imagesloaded

Seu site oficial: http://imagesloaded.desandro.com/

Por que é melhor do que usar:

$(window).load() 

Porque você pode querer carregar imagens dinamicamente, assim: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});
Yevgeniy Afanasyev
fonte
1
Na verdade, o imagesloaded não suporta a alteração do valor do atributo src entre navegadores. Você deve criar um novo elemento de imagem a cada vez. Experimente no Firefox e você verá o problema aparecendo.
Adrien Seja
Bom ponto, eu só testei no Google chrome e IE-11 ainda. Estava funcionando. Obrigado.
Yevgeniy Afanasyev
Eu adicionei esse problema em vários navegadores na minha pergunta stackoverflow.com/q/26927575 no ponto "O que você não pode fazer com o imagesloaded", consulte o problema relevante imagesLoaded no Github github.com/desandro/imagesloaded/issues/121
Adrien Seja
1

Dessa forma, você pode executar uma ação quando todas as imagens dentro do corpo ou qualquer outro contêiner (que depende da sua seleção) são carregadas. Solicitação pura, sem necessidade de pluggins.

var counter = 0;
var size = $('img').length;

$("img").load(function() { // many or just one image(w) inside body or any other container
    counter += 1;
    counter === size && $('body').css('background-color', '#fffaaa'); // any action
}).each(function() {
  this.complete && $(this).load();        
});
Mario Medrano
fonte
0

Minha solução é semelhante ao molokoloco . Escrito como função jQuery:

$.fn.waitForImages = function (callback) {
    var $img = $('img', this),
        totalImg = $img.length;

    var waitImgLoad = function () {
        totalImg--;
        if (!totalImg) {
            callback();
        }
    };

    $img.each(function () {
        if (this.complete) { 
            waitImgLoad();
        }
    })

    $img.load(waitImgLoad)
        .error(waitImgLoad);
};

exemplo:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
Mariusz Charczuk
fonte