¿Cómo puedo verificar si hay una imagen de fondo cargada?


154

Quiero establecer una imagen de fondo en la etiqueta del cuerpo, luego ejecutar un código, como este:

$('body').css('background-image','http://picture.de/image.png').load(function() {
    alert('Background image done loading');
    // This doesn't work
});

¿Cómo puedo asegurarme de que la imagen de fondo esté completamente cargada?


44
Simplemente asigne la misma URL al Image()objeto que tiene onloadevento.
Shadow Wizard es Ear For You

2
asegúrese de enrollar la url en cssurl()
bluescrubbie

Respuestas:


274

prueba esto:

$('<img/>').attr('src', 'http://picture.de/image.png').on('load', function() {
   $(this).remove(); // prevent memory leaks as @benweet suggested
   $('body').css('background-image', 'url(http://picture.de/image.png)');
});

esto creará una nueva imagen en la memoria y usará el evento de carga para detectar cuándo se carga el src.


10
Parece que la imagen se cargaría dos veces sin ningún motivo.
HyderA

49
@gAMBOOKa Se cargan una vez porque permanecen en la memoria del navegador. Esto es lo mismo, cuando coloca imágenes ocultas en la parte superior de su página y luego lo configura en CSS, por lo que las imágenes comienzan a descargarse antes del archivo css, se llama precarga.
jcubic

44
No estoy muy seguro, pero creo que te refieres al caché. No creo que haya algo como la memoria del navegador donde se almacenan los activos. Si se refiere a la memoria caché, recuerde que está agregando una solicitud HTTP adicional y es posible que todos los clientes no tengan habilitada la memoria caché.
HyderA

77
Ingrese esto en cualquier página que tenga jquery: javascript:void($('<img/>').attr('src', 'http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg').load(function() { $('html').css('background-image', 'url(http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg)'); }))y verifique las solicitudes HTTP en Firebug. Si he abierto una página de parpadeo con esta imagen abierta en otra pestaña, no hace ninguna solicitud HTTP, solo muestra esta imagen al instante. y cuando borro el caché y lo ejecuto hubo una solicitud.
jcubic

26
Una comparación entre esta prueba y esta muestra que debe llamar .remove()al $('<img/>')objeto para evitar una pérdida de memoria. Debería ver un consumo de memoria estable en la primera prueba y un aumento de memoria en la segunda. Después de unas pocas horas de ejecución en Chrome 28, la primera prueba toma 80 MB y la segunda 270 MB.
benweet

23

Tengo un complemento jQuery llamado waitForImagesque puede detectar cuándo se han descargado las imágenes de fondo.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);

Este complemento también es excelente para poder mostrar el progreso de carga utilizando la eachdevolución de llamada.
Soviut

1
@alex, ¿cómo debo verificar cada imagen de fondo para cada elemento en una clase? Intenté esto pero no parece hacerlo bien. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, function (loaded, count, success) {});
Relm

@Relm No lo estás usando correctamente. La segunda devolución de llamada es por imagen. Además, delay()no funciona así.
alex

16

Algo como esto:

var $div = $('div'),
  bg = $div.css('background-image');
  if (bg) {
    var src = bg.replace(/(^url\()|(\)$|[\"\'])/g, ''),
      $img = $('<img>').attr('src', src).on('load', function() {
        // do something, maybe:
        $div.fadeIn();
      });
  }
});

hola ... esto parece funcionar, aunque configuré bg.replace en bg.replace( ... , my_src ). Pero mi pregunta es: una vez que se carga $ ('<img>'), qué sucede exactamente con eso <img>... Quiero decir que no es real, es solo un marcador de posición ficticio, ¿verdad?
dsdsdsdsd

Correcto. El <img>nunca se inserta en el DOM; solo se usa para "engañar" al navegador para que cargue el archivo de imagen en la caché.
Colin

útil si no quieres invocar jQuery
vwvan


8

solución JS pura que agregará un precargador, establecerá la imagen de fondo y luego la configurará para la recolección de basura junto con su detector de eventos :

Version corta:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector("body");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
    bgElement.style.backgroundImage = `url(${imageUrl})`;
    preloaderImg = null;
});

Un poco más con buena transición de opacidad:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector(".bg-lazy");
bgElement.classList.add("bg-loading");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
  bgElement.classList.remove("bg-loading");
  bgElement.style.backgroundImage = `url(${imageUrl})`;
  preloaderImg = null;
});
.bg-lazy {
  height: 100vh;
  width: 100vw;
  transition: opacity 1s ease-out;
}

.bg-loading {
  opacity: 0;
}
<div class="bg-lazy"></div>


3
Solución infravalorada.
Tom Thomson

1
@TomThomson gracias Tom, encontré que la transición de la imagen no funcionaba correctamente, la arreglé
godblessstrawberry

6

Aquí hay un pequeño complemento que hice para permitirle hacer exactamente esto, también funciona en múltiples imágenes de fondo y múltiples elementos:

Leer el artículo:

http://catmull.uk/code-lab/background-image-loaded/

o vaya directamente al código del complemento:

http://catmull.uk/downloads/bg-loaded/bg-loaded.js

Tan solo incluya el complemento y luego instálelo en el elemento:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded();
</script>

Obviamente descargue el complemento y guárdelo en su propio alojamiento.

Por defecto, agrega una clase adicional "bg-loaded" a cada elemento coincidente una vez que se carga el fondo, pero puede cambiarlo fácilmente pasándole una función diferente como esta:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded({
      afterLoaded : function() {
         alert('Background image done loading');
      }
   });
</script>

Aquí hay un codepen que demuestra que funciona.

http://codepen.io/catmull/pen/Lfcpb


3

He encontrado una solución que funcionó mejor para mí y que tiene la ventaja de ser utilizable con varias imágenes (el caso no se ilustra en este ejemplo).

De la respuesta de @ adeneo a esta pregunta :

Si tiene un elemento con una imagen de fondo, como este

<div id="test" style="background-image: url(link/to/image.png)"><div>

Puede esperar a que se cargue el fondo al obtener la URL de la imagen y usarla para un objeto de imagen en javascript con un controlador de carga

var src = $('#test').css('background-image');
var url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');

var img = new Image();
img.onload = function() {
    alert('image loaded');
}
img.src = url;
if (img.complete) img.onload();

2

Hice un truco de javascript puro para hacer esto posible.

<div class="my_background_image" style="background-image: url(broken-image.jpg)">
<img class="image_error" src="broken-image.jpg" onerror="this.parentElement.style.display='none';">
</div>

O

onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";

css:

.image_error {
    display: none;
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.