Detectar carga de imagen como CSS background

Meleagant

Necesito saber a ciencia cierta en un momento dado si una imagen de background en CSS se ha cargado entera.

He probado a hacer la clásica función con callback que carga una imagen en JavaScript y cuando está cargada, cambiar el fondo, pero no se puede pasar un objeto Image como parámetro, por lo que tengo que hacer:

elemento.style.backgroundImage = "url('fondo.png' ) ";

Al hacer esto, da igual si la imagen ya estaba cargada en caché, vuelve a pedírsela al servidor. La carga es mucho más rápida porque cuando recibe la respuesta del servidor, utiliza la imagen en caché, pero durante el tiempo que pasa, unos 400ms, el fondo no se cambia.

He pensado que sería mejor cargar los fondos como distintas clases, y cuando estén cargados cambiar la clase del elemento. Pero no encuentro ninguna manera de detectar cuándo un background CSS ha terminado de cargarse.

No es necesario que sea un evento, podría detectarlo mediante polling si fuera necesario, ya que es para un juego y el bucle se ejecuta constantemente.

KoRMuZ

#1 Si no recuerdo mal, jQuery tenía un evento "load". No lo recuerdo bien, o si funcionará exactamente con tu caso, pero puedes echarle un ojo.

EDIT: Vale, ese método está desechado desde hace tiempo. Ahora se usa on.

$("#elem").on('load', manejadorDeEvento)
1 respuesta
Meleagant

#2 Lo he estado echando un ojo. El tema es que los backgrounds de CSS no son elementos del DOM, así que no creo que se les pueda aplicar ese sistema.

Técnicamente un DIV puede estar cargado en el DOM pero su imagen de fondo puede seguir todavía cargando.

1 respuesta
KoRMuZ

#3 creo que aquí tienes la solución. No se hace de forma nativa, pero supongo que te puede servir.

2 respuestas
MegalomaniaC

#4 Iba a recomendar el mismo.

Meleagant

#4 Muchas gracias :)

No me va servir porque es un plugin de jQuery y no quiero meter una librería que no necesito, tengo que economizar bien el espacio, pero la verdad es que no he encontrado otra opción que haga lo mismo.

Lo que voy a hacer es meter distintas clases CSS para cada fondo y crear DIVs ocultos con dichas clases. Al terminar la carga de objetos Image con el mismo SRC que el background de los div, sé que ya están preparados y entonces sólo tengo que cambiar la clase del DIV en cuestión para que tenga el fondo distinto.

Esto es todo teórico, así que a cruzar los dedos xD

MisKo

Inicialmente deja el fondo sin imagen.

Carga las imagenes con javascript, sin divs ocultos, solo por codigo y, en el onload de la imagen la pones de fondo.

1 respuesta
Meleagant

#7 Eso es lo que intenté hacer en #1, pero no puedes pasar un objeto Imagen como fondo CSS, tienes que pasarle la URL de la imagen, lo que genera otra petición HTTP.

MisKo

Si, genera otra peticion HTTP, pero al estar ya cargada en el cliente, no te la va a volver a cargar, por lo que se va a mostrar inmediatamente.

1 respuesta
Meleagant

#9 No es por tocar los cojones, pero ¿te has leído #1?

Al hacer esto, da igual si la imagen ya estaba cargada en caché, vuelve a pedírsela al servidor. La carga es mucho más rápida porque cuando recibe la respuesta del servidor, utiliza la imagen en caché, pero durante el tiempo que pasa, unos 400ms, el fondo no se cambia.

MisKo

No te preocupes, no tocas los cojones, todo sirve para aprender y puede que me equivoque =)

Cuando una imagen se carga desde cache, el trabajo en servidor es nulo, ya que el explorador controla la URL de la imagen, la busca en cache, y la carga desde ahí. El tiempo de carga depende del cliente y de su ordenador ( por eso es cache y no una carga completa del servidor ). Me parece muy raro que te tarde 400ms en cargar una imagen de cache, cuando por ejemplo, yo con ajax, he realizado consultas a bases de datos, querys y tal, en menos de ese tiempo ( no es lo mismo, pero es para poner una comparación ).

Si no es mucha molestia y se puede ver, pasame si quieres la URL de la página donde lo estás modificando y te miro cuanto tiempo me tarda a mi en hacer ese cambio.

1 respuesta
Meleagant

#11 La página ahora mismo no puedo enseñarla porque es un trabajo para un cliente que me ha exigido no publicar nada de momento.

Pero vamos, te digo 100% seguro que está enviando dos peticiones HTTP porque lo veo en el tráfico de red. Una vez que recibe la respuesta HTTP la imagen se carga inmediatamente, porque la respuesta es un 304, que indica que la imagen no se ha modificado desde que se cargó en caché, pero tiene que esperar a recibir ese mensaje 304, lo que causa un retardo pequeño pero perceptible a la hora de cambiar el fondo.

Estoy bastante seguro de que la única forma de hacerlo bien es la que he comentado en #6, pero no lo he implementado aún porque ahora mismo no es una prioridad.

MisKo

Bueno, si no se puede ver, no lo puedo comprobar

No te preocupes si no es una prioridad, pero vamos, como te he dicho, no deberia tardarte, te dejo algo que acabo de comprobar yo ;)

1 respuesta
Meleagant

#13 ¿Cómo lo estás cambiando? Este es el código que estoy usando yo, una vez que recibo el callback de onload del Image:

containerDiv.style.backgroundImage = "url('media/img/background.png')";
containerDiv.style.backgroundPosition = "100% 100%";
containerDiv.style.backgroundSize = "cover";

Previamente he creado un objeto Image con el src "media/img/background.png", pero como ya digo ese objeto no llega a ser visible en ningún momento, ni sirve para otra cosa más que para cargar la imagen.

1 respuesta
MisKo

#14 Te he hecho una prueba rápida de lo que estaba haciendo.

http://jsfiddle.net/3H7rg/1/

1 respuesta
Meleagant

#15 Pues sí, he estado trasteando con ella y ahí no envía dos peticiones HTTP. He probado en mi servidor local y tampoco, pero cuando cargo el mismo proyecto desde Dropbox, sí:

A lo mejor van por ahí los tiros, puede que haya alguna configuración del servidor que le fuerce a repetir peticiones, es la única explicación lógica que le encuentro.

Usuarios habituales

  • Meleagant
  • MisKo
  • MegalomaniaC
  • KoRMuZ