Carregar uma imagem de fundo de baixa resolução primeiro, depois uma de alta resolução

Estou a tentar optimizar o tamanho do meu site quando está a ser distribuído ao cliente. Baixei para 1,9 MB e 29KB quando Cache. A questão é que a primeira carga contém uma imagem que é muito pouco otimizada para dispositivos móveis; tem uma resolução de 1080p.

então estou à procura de um método que me permita primeiro carregar uma versão de baixa resolução (min.bg.jpg) e uma vez que o site tenha carregado, use uma versão de alta resolução-ou mesmo uma com uma resolução perto do dispositivo que está a ser usado (NNNxNNN.bg.jpg ou apenas bg.jpg).

o fundo é definido usando CSS, tal como toda a gente esperaria. É aplicado ao corpo e toda a declaração se parece com isto:

body {
    background: url("/cdn/theme/images/bg.jpg");
    color: white;
    height: 100%;
    width: 100%;
    background-repeat: no-repeat;
    background-position: 50% 50%;
    background-attachment: fixed;
}

Agora, eu quero mudar isso para usar min.bg.jpg em vez da primeira carga, e depois algo assim:

jQuery(function(){
    jQuery("body").[...]
});
Para que lado continuo a descarregar assíncronamente o novo fundo e a inseri-lo como a nova imagem de fundo do CSS?

Para mostrar algumas diferenças, aqui está um exemplo da versão principal e mini que eu sou utilizar para ensaio:

[email protected] ~/Work/BIRD3/cdn/theme/images $ file *.jpg
bg.jpg:     JPEG image data, EXIF standard
min.bg.jpg: JPEG image data, JFIF standard 1.01
[email protected] ~/Work/BIRD3/cdn/theme/images $ du -h *.jpg
1,0M    bg.jpg
620K    min.bg.jpg
Author: Ingwie Phoenix, 2015-01-14

6 answers

Este é o método que eu uso...

CSS:

#div_whatever {
   position: whatever;
   background-repeat: no-repeat;
   background-position: whatever whatever; 
   background-image: url(dir/image.jpg);
   /* image.jpg is a low-resolution at 30% quality. */
}

#img_highQuality {
    display: none;
}

HTML:

<img id="img_highQuality" src="dir/image.png">
<!-- img.png is a full-resolution image. -->

<div id="div_whatever"></div>

JQUERY:

$("#img_highQuality").off().on("load", function() {
    $("#div_whatever").css({
        "background-image" : "url(dir/image.png)"
    });
});
// Side note: I usually define CSS arrays because
// I inevitably want to go back and add another 
// property at some point.

O Que Acontece:

  1. uma versão de baixa resolução do fundo carrega rapidamente.
  2. Entretanto, a versão de resolução mais alta está a carregar como uma imagem escondida. Quando a imagem de alta resolução é carregada, o jQuery troca a imagem de baixa resolução do div com a versão de alta resolução.

PUROS JS Versão

Este exemplo seria eficiente para mudar um para muitos elementos.

CSS:

.hidden {
   display: none;
}

#div_whatever {
   position: whatever;
   background-repeat: no-repeat;
   background-position: whatever whatever; 
   background-image: url(dir/image.jpg);
   /* image.jpg is a low-resolution at 30% quality. */
}

HTML:

<div id="div_whatever"></div>
<img id="img_whatever" class="hidden" src="dir/image.png" onload="upgradeImage(this);">

JAVASCRIPT:

function upgradeImage(object) {
    var id = object.id;
    var target = "div_" + id.substring(4);

    document.getElementById(target).style.backgroundImage = "url(" + object.src + ")";
}

ACTUALIZAR / MELHORAR (1/31/2017)

Esta melhoria é inspirada pelo excelente pontoDe gdbj de que a minha solução resulta na especificação do caminho da imagem em três locais. Embora eu não tenha usado gdbj's addClass() técnica, o seguinte código jQuery é modificado para extrair o caminho da imagem (ao invés de ser conectado ao código jQuery). Mais importante, esta versão permite múltiplas substituições de imagens de baixa resolução para alta resolução.

CSS

.img_highres {
  display: none;
}

#div_whatever1 {
  width: 100px;
  height: 100px;
  background-repeat: no-repeat;
  background-position: center center;
  background-image: url(PATH_TO_LOW_RES_PHOTO_1);
}

#div_whatever2 {
  width: 200px;
  height: 200px;
  background-repeat: no-repeat;
  background-position: center center;
  background-image: url(PATH_TO_LOW_RES_PHOTO_2);
}

HTML

<div id="div_whatever1"></div>
<img id="img_whatever1" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_1">

<div id="div_whatever2"></div>
<img id="img_whatever2" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_2">

JQUERY

  $(function() {
      $(".img_highres").off().on("load", function() {
         var id = $(this).attr("id");
         var highres = $(this).attr("src").toString();
         var target = "#div_" + id.substring(4);
         $(target).css("background-image", "url(" + highres + ")");
      });
   });

O Que Acontece:

  1. as imagens de baixa resolução são carregadas para cada uma das divas com base no seu CSS. configuração da imagem de fundo. (Notar que o CSS também fixa o div para o dimensao.)
  2. Entretanto, as fotos de alta resolução estão a ser carregado como imagens escondidas (todas a partilhar um nome de classe de img_ highres).
  3. uma função jQuery é despoletada cada vez que uma foto img_highres completa o carregamento.
  4. a função jQuery lê a localização da imagem src, e muda a imagem de fundo do div correspondente. Na exemplo acima, a Convenção de nomenclatura é "div_ [nome]" para as divs visíveis e " img_ [mesmo nome] " para as imagens de alta resolução carregadas na fundo.
 13
Author: Alan M., 2017-05-23 12:18:18
Vamos tentar um básico:
<img border="0" 
     style="background:url(http://i.stack.imgur.com/zWfJ5.jpg) no-repeat; 
            width:1920px;
            height:1200px"
     src="http://i.stack.imgur.com/XOYra.jpg" width="1920" height="1200" />

zWfJ5.jpg é a versão de baixa resolução, e XOYra.jpg é a versão de alta resolução.

Se há uma maneira de organizar o carregamento de modo que a imagem de fundo mostra primeiro, este pode ser o mais simples que eu consigo pensar.

Em baixa resolução 44k: low resolution 44k:

E a alta resolução é de 1,16 M high resolution is 1.16M

Resultado:

JsFiddled here (this needs a bigger image for loading comparison. )

 21
Author: Milche Patern, 2017-10-21 09:08:33
Um pouco tarde, mas pode usar esta solução extremamente simples.: Você pode colocar as duas imagens no fundo do css:
  background-image: url("high-res.jpg"),url("low-res.jpg");

O navegador irá mostrar o punho de imagem de baixa resolução, em seguida, mostrar a alta resolução sobre a baixa resolução quando tiver sido carregada.

 3
Author: user7956100, 2018-03-31 07:54:39

Normalmente optimizaria a imagem usando o Grunt ou uma ferramenta online como o Tiny PNG para reduzir o tamanho do ficheiro.

Então você poderia optar por adiar o carregamento das imagens, eu achei o seguinte artigo útil quando se tratava de desafiar imagens - https://www.feedthebot.com/pagespeed/defer-images.html

O artigo discute a utilização de uma imagem base64 para o carregamento inicial e, em seguida, para o carregamento da imagem de alta qualidade. A marca de imagem mencionada no o artigo é o seguinte...

<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">

O JavaScript mencionado no artigo é o seguinte...

<script type="text/javascript" async>
function init() {
    var imgDefer = document.getElementsByTagName('img');
    for (var i=0; i<imgDefer.length; i++) {
        if(imgDefer[i].getAttribute('data-src')) {
            imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
        }
    }
}
window.onload = init;
</script>
Espero que isto ajude.
 1
Author: steffcarrington, 2015-07-21 19:08:34
Já tentou usar sprites CSS para ajudar a conseguir o que quer? http://css-tricks.com/css-sprites/
 0
Author: Caleb Hutchinson, 2015-01-14 05:12:10
Todas as respostas acima funcionam principalmente com um pequeno ajuste, mas aqui está a maneira que eu acho curta e simples de começar.

Nota: - Descomentar o código carregar a imagem de alta resolução para uso, uma função de latência é apenas para simular uma rede lenta. - Na verdade, este método não carrega 2 recursos (baixo e alto) simultâneos, mas é aceitável porque baixo recurso não vai levar muito tempo para carregar. - Copie o código inteiro e corra para um rápido verificar.

<!DOCTYPE html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>

    <style type="text/css">
      
    </style>
  </head>

  <body>
    <!-- Load low res image first -->
    <img style="width: 400px; height: auto;" alt="" src="https://s3-ap-southeast-1.amazonaws.com/wheredat/banner-low-quality/banner_20180725_123048.jpg" onload="upgrade(this)">
  </body>
  
  <script type="text/javascript">

	function upgrade(image){

                // After load low res image, remove onload listener.

		// Remove onload listener.
		$(image).prop("onload", null);

                // Load high resolution image.
                // $(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');

		// Simulate slow network, after 1.5s, the high res image loads.
		sleep(1500).then(() => {
		    // Do something after the sleep!

			// Load a high resolution image.
			$(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');
		});	
	}

	// Sleep time expects milliseconds
	function sleep (time) {
	  return new Promise((resolve) => setTimeout(resolve, time));
	}

  </script>
  
</html>
 0
Author: Nguyen Tan Dat, 2018-07-25 05:39:08