Carregar uma imagem de fundo de baixa resolução primeiro, depois uma de alta resolução
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
6 answers
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:
- uma versão de baixa resolução do fundo carrega rapidamente. 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:
- 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.) 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).
- uma função jQuery é despoletada cada vez que uma foto img_highres completa o carregamento.
- 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.
<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.
E a alta resolução é de 1,16 M
Resultado:
JsFiddled here (this needs a bigger image for loading comparison. )
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.
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.
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>