Cómo implementar la carga progresiva de imágenes

Esta es una técnica que se encuentra en muchas aplicaciones web ahora. También me intrigó cuando lo noté en Medium por primera vez. Me hizo buscar más sobre cómo se hizo e incluso probar algunas muestras.

El concepto básico detrás de esto es la carga progresiva de imágenes, que a menudo se usa en muchos sitios web. A menudo, las imágenes utilizadas en sitios web con mucho contenido son de gran tamaño y, por lo tanto, los sitios web prefieren “cargar lentamente” las imágenes hacia el final o cuando realmente se necesita. Por ejemplo, si una imagen aparece solo después de algunos párrafos de texto, solo después de que el usuario se haya desplazado por el texto, la imagen comenzará a cargarse. De esta forma, el contenido legible se pone a disposición del usuario casi de inmediato sin tener que esperar las imágenes. Esa es la parte del concepto.

El factor sorpresa viene debido a algunas pequeñas improvisaciones que le hacen a esto. En el caso de Medium, lo que sucede es que primero descargan una versión más pequeña de la imagen (una miniatura), luego esta miniatura se muestra en el área de la imagen con alguna función de desenfoque para darle ese efecto borroso. Al hacerlo, la ‘textura’ se siente muy original porque es una versión en miniatura de la imagen original. Después de que la imagen completa se haya cargado, el lienzo se reemplaza con la imagen original utilizando algunos efectos de transición para producir ese ‘efecto sorpresa’.

No he leído (todavía) sobre cómo Quora lo hace exactamente, pero mirándolo, el proceso parece ser similar.

Hay una publicación mediana muy detallada de José M. Pérez sobre esto. También llegué a saber cómo se hizo exactamente esto a través de su publicación. Puede leer más sobre la carga de imágenes progresivas aquí: Procesamiento de imágenes progresivas.

Fui el ingeniero que implementó esta función en Quora (llamada carga progresiva de imágenes). Hablaré sobre cómo implementar esto genéricamente en esta respuesta:

En el HTML , quieres tener algo como:


). Las etiquetas Img no tienen una forma limpia de establecer las dimensiones de las imágenes si la relación ancho-alto de la imagen de salida deseada es potencialmente diferente a la de su imagen de origen (el src de datos dentro de la etiqueta del lienzo).

Tenga en cuenta que tanto en el canvas como en las etiquetas img , las imágenes están en el atributo data-src lugar del atributo src . Sin Javascript, la página estaría en blanco.

A continuación, en Javascript , tenemos algo como lo siguiente para cargar las imágenes de marcador de posición:

función loadPlaceholderImage (marcador de posición) {
if (placeholder.getAttribute (‘data-src’)) {
var placeholder_img = nueva imagen ();
placeholder_img.src = placeholder.getAttribute (‘data-src’);
var ancho = placeholder.getAttribute (‘ancho’);
var height = placeholder.getAttribute (‘height’);
var ctx = placeholder.getContext (‘2d’);
placeholder_img.addEventListener (‘load’, function () {
ctx.drawImage (
placeholder_img,
0,
0,
anchura,
altura);
}, falso);
}
}

función loadPlaceholderImages () {
marcadores de posición var = document.querySelectorAll (‘canvas [data-src]’);
// Carga progresivamente las imágenes de marcador de posición en la carga de la página
[] .forEach.call (marcadores de posición, loadPlaceholderImage);
}

// Queremos cargar las imágenes de marcador de posición lo antes posible.
loadPlaceholderImages ();

Lo que esto significa es:

  • Tan pronto como el archivo Javascript se analiza y ejecuta, ejecutamos loadPlaceholderImages() .
  • loadPlaceholderImages() itera sobre todos los elementos de canvas en nuestro HTML que tienen un atributo data-src , y para cada uno de ellos, llame a loadPlaceholderImage() .
  • loadPlaceholderImage() luego intenta cargar las imágenes de marcador de posición creando un objeto Image y configurando el src del objeto Image a lo que esté en el data-src del canvas .
  • Luego, tan pronto como el objeto Image complete la carga, llamaremos ctx.drawImage , que dibuja ese objeto Image dentro del canvas , con las dimensiones especificadas en el HTML.

Una vez que este fragmento de Javascript completa la ejecución, el usuario verá la imagen borrosa del marcador de posición.

Para cargar las imágenes reales de resolución completa, en Javascript , tenemos:

función loadDeferredImages () {
var imgDefer = document.querySelectorAll (‘img [data-src]’);
para (var i = 0; i loadDeferredImage (imgDefer [i]);
}
}

función loadDeferredImage (img_element) {
if (img_element.getAttribute (‘data-src’)) {
img_element.setAttribute (‘src’, img_element.getAttribute (‘data-src’));
img_element.removeAttribute (‘data-src’);
img_element.addEventListener (‘load’, function () {
img_element.style.opacity = 1;

// ocultar la imagen del marcador de posición
var placeholder_elm = img_element.previousElementSibling;
if (placeholder_elm && placeholder_elm.classList.contains (‘qtext_image_placeholder’)) {
// Sin tiempo de espera, veríamos un destello blanco antes de que se cargue la imagen.
setTimeout (function () {
placeholder_elm.style.visibility = ‘hidden’;
}, 1000);
}
});
}
}

window.onload = loadDeferredImages;

De manera similar, esto está iterando sobre todos los elementos img con atributos data-src en el HTML, y activando el navegador para descargar esas imágenes configurando data-src como src. Una vez que se han cargado las imágenes, establezca la opacity del elemento en 1 y oculte la imagen del marcador de posición.

En la mayoría de los casos, todo se verá correcto sin el último paso de ocultar la imagen del marcador de posición, pero en los casos en que la imagen real sea transparente, si no oculta la imagen del marcador de posición, se vería bastante extraño.

Para ver una demostración de cómo funciona esto, consulte: carga progresiva de imágenes – JSFiddle

Cómo Medium carga la imagen progresivamente comparte un enfoque similar pero ligeramente diferente, así que definitivamente échale un vistazo también.