Como carregar imagens dinamicamente (ou preguiçosamente) quando os usuários as rolam para exibição

97

Tenho notado isso em vários sites "modernos" (por exemplo, Facebook e pesquisa de imagens do Google), onde as imagens abaixo da dobra carregam apenas quando o usuário rola a página para baixo o suficiente para trazê-los para dentro da região da janela de visualização visível ( na fonte de exibição, a página mostra Número X de <img>tags, mas eles não são obtidos do servidor imediatamente ). Como é chamada essa técnica, como funciona e em quantos navegadores ela funciona. E existe um plugin jQuery que pode atingir esse comportamento com codificação mínima.

Editar

Bônus: alguém pode explicar se existe um "onScrolledIntoView" ou evento semelhante para elementos HTML. Se não, como esses plug-ins funcionam?

Salman A
fonte
Você precisa apenas de carregamento lento de imagens? Se você precisa de carregamento lento de conteúdo, o plugin de rolagem infinita é a resposta certa
soju
@rsp @jwegner @Nicholas sinto muito, mas não é isso que Salman está perguntando.
Alec Smart
@soju: Só estou interessado em imagens de carregamento lento; mas posso olhar para outras possibilidades em algum momento no futuro (bastante distante).
Salman A
21
Faz você se perguntar por que o comportamento padrão de um navegador não é carregar apenas imagens que são visíveis. Imagine quanta largura de banda poderia ter sido economizada nos últimos 18 anos se fosse esse o caso!
Matthew Lock,
2
Embora eu entenda a razão por trás do carregamento lento ... Sinceramente, não suporto quando visito um site que utiliza esse método. O piscar das imagens me deixa louco! :)
Booski

Respostas:

64

Algumas das respostas aqui são para página infinita. O que Salman está pedindo é o carregamento lento de imagens.

Plugar

Demo

EDIT: Como funcionam esses plug-ins?

Esta é uma explicação simplificada:

  1. Encontre o tamanho da janela e encontre a posição de todas as imagens e seus tamanhos
  2. Se a imagem não estiver dentro do tamanho da janela, substitua-a por um marcador de posição do mesmo tamanho
  3. Quando o usuário rola para baixo e a posição da imagem <rolar + altura da janela, a imagem é carregada
Alec Smart
fonte
Na aplicação, eles não funcionam da mesma forma? Um pergaminho infinito em uma única coluna de imagens seria o mesmo que carregá-las lentamente, certo? Talvez eu esteja confuso.
jwegner
1
@jwegner A rolagem infinita permite adicionar novos itens ao final da página quando o usuário alcança (ou se aproxima) do final. Imagens com carregamento lento podem ter marcadores de posição com as mesmas dimensões na página, com as próprias imagens carregadas na rolagem. Portanto, o último pode carregar lentamente sem afetar o layout da página.
Annika Backstrom
Isso está funcionando bem em navegadores de desktop e iOS, mas não funciona no Android (incluindo 3.x / 4.x). Alguma ideia do porquê? o evento de rolagem não é compatível?
lahsrah
Eu estava examinando a documentação deste plugin e parece ser muito bom. Vou usar isso no meu próximo projeto.
The Muffin Man
aqui está um plugin relacionado, que provavelmente funciona da mesma maneira: afarkas.github.io/lazysizes exceto que eu acredito que é muito mais robusto e usa mais do que já está lá (não há necessidade de espaço reservado, por exemplo, mas você pode tê-lo se você quer).
cregox
10

Dave Artz da AOL deu uma ótima palestra sobre otimização na jQuery Conference Boston no ano passado. AOL usa uma ferramenta chamada Sonar para carregamento sob demanda com base na posição de rolagem. Verifique no código os detalhes de como ele compara scrollTop (e outros) ao deslocamento do elemento para detectar se parte ou todo o elemento está visível.

jQuery Sonar

Dave fala sobre o Sonar nesses slides . O sonar começa no slide 46, enquanto a discussão geral sobre "carga sob demanda" começa no slide 33.

Annika Backstrom
fonte
Eu me pergunto como isso se compara ao lazyload de Appelsinii? É mais leve? Funciona em todos os navegadores? Lembro que o lazyload não funciona no Chrome.
deathlock
8

Eu vim com meu próprio método básico que parece funcionar bem (até agora). Provavelmente, há uma dúzia de coisas que alguns dos scripts populares abordam nas quais não pensei.

Observação - esta solução é rápida e fácil de implementar, mas obviamente não é ótima para desempenho. Definitivamente, olhe para o novo Intersection Observer, conforme mencionado por Apoorv e explicado por developers.google se o desempenho for um problema.

O JQuery

$(window).scroll(function() {
    $.each($('img'), function() {
        if ( $(this).attr('data-src') && $(this).offset().top < ($(window).scrollTop() + $(window).height() + 100) ) {
            var source = $(this).data('src');
            $(this).attr('src', source);
            $(this).removeAttr('data-src');
        }
    })
})

Amostra de código html

<div>
    <img src="" data-src="pathtoyour/image1.jpg">
    <img src="" data-src="pathtoyour/image2.jpg">
    <img src="" data-src="pathtoyour/image3.jpg">
</div>

Explicado

Quando a página é rolada, cada imagem na página é verificada.

$(this).attr('data-src') - se a imagem tiver o atributo data-src

e a que distância essas imagens estão da parte inferior da janela.

$(this).offset().top < ($(window).scrollTop() + $(window).height() + 100)

ajuste + 100 para o que quiser (- 100 por exemplo)

var source = $(this).data('src');- obtém o valor de data-src=também conhecido como o url da imagem

$(this).attr('src', source); - coloca esse valor no src=

$(this).removeAttr('data-src'); - remove o atributo data-src (para que seu navegador não desperdice recursos mexendo com as imagens que já foram carregadas)

Adicionando ao Código Existente

Para converter seu html, em um editor, basta pesquisar e substituir src="porsrc="" data-src="

Hastig Zusammenstellen
fonte
perfeito. abençoe fam 🙏
LifterCoder
5

Existe um plugin de rolagem infinita muito bom aqui

Eu mesmo nunca programei um, mas imagino que seja assim que funciona.

  1. Um evento está vinculado à rolagem da janela

    $(window).scroll(myInfinteScrollFunction);
  2. A função chamada verifica se o topo da rolagem é maior que o tamanho da janela

    function myInfiniteScrollFunction() {  
        if($(window).scrollTop() == $(window).height())  
        makeAjaxRequest();  
    }
  3. Uma solicitação AJAX é feita, especificando em qual resultado # começar, quantos obter e quaisquer outros parâmetros necessários para a extração de dados.

    $.ajax({
        type: "POST",
        url:  "myAjaxFile.php",
        data: {"resultNum": 30, "numPerPage": 50, "query": "interesting%20icons" },
        success: myInfiniteLoadFunction(msg)
    });
  4. O ajax retorna algum conteúdo (provavelmente formatado em JSON) e os passa para a função loadnig.

Espero que isso faça sentido.

Jwegner
fonte
3

O carregamento lento de imagens anexando listener a eventos de rolagem ou usando setInterval é altamente sem desempenho, pois cada chamada para getBoundingClientRect () força o navegador a refazer o layout de toda a página e introduzirá considerável confusão em seu site.

Use Lozad.js (apenas 569 bytes sem dependências), que usa IntersectionObserver para carregar lentamente as imagens com desempenho.

Apoorv Saxena
fonte
Polyfill pode ser adicionado dinamicamente caso o suporte do navegador não esteja disponível
Apoorv Saxena
O suporte ao navegador está muito melhor hoje em dia - posso usar
Hastig Zusammenstellen
1

O canivete suíço de carregamento lento de imagens é o ImageLoader da YUI .

Porque esse problema é mais do que simplesmente observar a posição de rolagem.

Arnaud Meuret
fonte
0

Demonstração deste link funciona para mim

1. Carregue o plugin jQuery loadScroll após a biblioteca jQuery, mas antes da tag de fechamento do corpo.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script><script src="jQuery.loadScroll.js"></script>

2. Adicione as imagens em sua página da web usando o atributo Html5 data-src. Você também pode inserir marcadores de posição usando o atributo src do img regular.

<img data-src="1.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="2.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="3.jpg" src="Placeholder.jpg" alt="Image Alt">

3. Chame o plugin nas tags img e especifique a duração do efeito fadeIn conforme suas imagens são exibidas

$('img').loadScroll(500); // in ms
Vebs
fonte
0

Estou usando o jQuery Lazy . Levei cerca de 10 minutos para testar e uma ou duas horas para adicionar à maioria dos links de imagem em um dos meus sites ( CollegeCarePackages.com ). Não tenho nenhum relacionamento (nenhum / zero) de qualquer tipo com o desenvolvedor, mas isso me economizou muito tempo e basicamente ajudou a melhorar nossa taxa de rejeição para usuários de celular e eu agradeço isso.

Cliff Ribaudo
fonte