javascript - img - title html
Cómo cargar imágenes perezosas y ponerlas a disposición para imprimirlas (3)
Algunos sitios web tienen muchas imágenes, por lo que la carga lenta parece apropiada para reducir los tiempos de carga y el consumo de datos. ¿Pero qué pasa si también necesita admitir la impresión para ese sitio web?
Quiero decir, puedes intentar detectar el evento de impresión y luego cargar las imágenes, con algo como esto:
HTML
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
Nota: esta es una imagen falsa de gif de uno por uno de píxeles.
JavaScript
window.addEventListener(''DOMContentLoaded'', () => {
img = document.querySelector(''img'');
var isPrinting = window.matchMedia(''print'');
isPrinting.addListener((media) => {
if (media.matches) {
img.src = ''http://unsplash.it/500/300/?image=705'';
}
})
});
Nota: si intenta esto en un área de juegos de códigos, elimine el evento DOMContentLoaded
(o simplemente JSFiddle estos: JSFiddle | Codepen ).
Nota: no me preocupé por el uso de onbeforeprint
y onafterprint
por razones obvias .
Esto funcionará bien si la imagen se almacena en caché, pero de nuevo ese no es precisamente el punto. Todas las imágenes deben cargarse y luego aparecer en la pantalla de impresión.
¿Tienes alguna idea? ¿Alguien ha implementado con éxito un complemento de carga lenta listo para imprimir?
Actualizar
He intentado redirigir al usuario después de detectar el cuadro de diálogo de impresión, a una versión marcada del sitio web, también conocido como website.com?print=true
donde la carga lenta está desactivada y todas las imágenes se cargan normalmente.
Este método se mejora al aplicar el método window.print()
en esta versión marcada para impresión lista de la página, abriendo un nuevo cuadro de diálogo de impresión una vez que todas las imágenes terminan de cargarse y mostrando un mensaje de " espéralo " mientras tanto en el parte superior de la página.
Nota importante: este método se probó en Chrome, no funciona en Firefox ni en Edge (de ahí que esto no sea una respuesta, sino un testimonio).
Funciona en Chrome porque el cuadro de diálogo de impresión se cierra cuando redirecciona a otro sitio web (en este caso, la misma URL pero está marcada). En Edge y Firefox, el diálogo de impresión es una ventana real y no la cierra, por lo que es bastante inutilizable.
Escribí un complemento de jquery de carga lenta que admite mostrar imágenes en impresión utilizando los eventos window.onbeforeprint y mediaQueryListeners. https://github.com/msigley/Unveil-EX/
Según la funcionalidad que desee, no estoy seguro de qué es lo que desea hacer. Como desarrollador, realmente no tenemos control sobre el navegador de un usuario. Aquí están mis pensamientos sobre por qué esto no es completamente posible.
Enganchar el evento para ir y cargar las imágenes que faltan no te permitirá garantizar que las imágenes saldrán del servidor a tu página. Más específicamente, el PDF generado para su vista previa de impresión se generará antes de que sus imágenes se carguen, el
img.src = "..."
es asíncrono.onbeforeprint
, también seonbeforeprint
con problemas similares cononbeforeprint
. A veces funciona, a veces no (ejemplo, su violín funcionó al probar en safari, pero no en Chrome)No puede detener o detener la llamada de impresión: no puede forzar al navegador a esperar a que su imagen termine de cargarse en el contexto de carga lenta. (Leí algo sobre el uso de las alertas para lograr esto una vez, pero para mí me parecía muy intrépido, era más disuasivo para imprimir que para detener)
No puede obligar a
img.src
a obtener esos datos de forma síncrona en un contexto de cargaimg.src
. Hay algunos métodos para hacer esto, pero son hacks inteligentes: se hace referencia como maldad pura y es posible que no funcionen siempre. Encontré otro enlace con un enfoque similar.
Por lo tanto, tenemos un problema: si las imágenes no se cargan en el momento en que se dispara el evento de impresión, no podemos forzar al navegador a esperar hasta que finalicen. Claro, podemos enganchar e ir obteniendo esas imágenes en la impresión, pero como se indica arriba, no podemos esperar a que esos recursos se carguen antes de que aparezca la vista previa de impresión.
Solución potencial (inspirada en los enlaces del punto tres y en este enlace )
Casi podría salirse con la suya haciendo un XMLHttpRequest síncrono. Las peticiones XMLHTTP sincrónicas no le permitirán cambiar el tipo de respuesta, siempre son cadenas. Sin embargo, puede convertir el valor de cadena en un arrayBuffer codificado en una cadena codificada en base-64, y configurar el src en un dataURL (ver el enlace que hace referencia a hacks inteligentes). Sin embargo, cuando intenté esto, recibí un error. El jsfiddle - así sería posible, si las cosas estuvieran configuradas correctamente, en teoría. No me atrevo a decir que sí, porque no pude hacer que el violín trabajara con lo siguiente (¡pero es una ruta que puedes explorar!).
var xhr = new XMLHttpRequest();
xhr.open("GET","http://unsplash.it/500/300/?image=705",false);
xhr.send(null);
if (request.status === 200) {
//we cannot change the resposne type in synchronous XMLHTTPRequests
//we can convert the string into a dataURL though
var arr = new Uint8Array(this.response);
// Convert the int array to a binary string
// We have to use apply() as we are converting an *array*
// and String.fromCharCode() takes one or more single values, not
// an array.
var raw = String.fromCharCode.apply(null,arr);
// This is supported in modern browsers
var b64=btoa(raw);
var dataURL="data:image/jpeg;base64,"+b64;
img.src = dataURL;
}
Trabajar para mejorar la experiencia del usuario
Algo que podría hacer es tener un texto que solo se muestra en la versión impresa de su página (a través de @print
css media) que dice "las imágenes todavía se están cargando, cancele su solicitud de impresión e intente nuevamente" y cuando las imágenes hayan terminado de cargarse, elimine ese "aún en espera de recursos intente nuevamente el mensaje" del DOM. Más lejos, podría envolver su contenido principal dentro de un elemento que invierta la pantalla a nada cuando el contenido no se carga, por lo que todo lo que ve es ese mensaje en el cuadro de diálogo de vista previa de impresión.
Saliendo del código que publicaste, esto podría parecerse a lo siguiente (ver jsfiddle actualizado):
CSS
.printing-not-ready-message{
display:none;
}
@media print{
.printing-not-ready-message{
display:block;
}
.do-not-print-content{
display:none;
}
}
HTML
<div class="printing-not-ready-message">
Images are still loading please cancel your preview and try again shortly.
</div>
<div class="do-not-print-content">
<h1>Welcome to my Lazy Page</h1>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
<p>Insert some comment about picture</p>
</div>
JavaScript
window.addEventListener(''DOMContentLoaded'', () => {
img = document.querySelector(''img'');
var isPrinting = window.matchMedia(''print'');
isPrinting.addListener((media) => {
if (media.matches) {
img.src = ''http://unsplash.it/500/300/?image=705'';
//depending on how the lazy loading is done, the following might
//exist in some other call, should happen after all images are loaded.
//There is only 1 image in this example so this code can be called here.
img.onload = ()=>{
document.querySelector(".printing-not-ready-message").remove();
document.querySelector(".do-not-print-content").className=""
}
}
})
});
Soy el autor de la vanilla-lazyload comandos vanilla-lazyload y recientemente he desarrollado una función que hace posible la impresión de todas las imágenes.
Navegador cruzado probado utilizando este código de repo que se encuentra aquí .
¡Echa un vistazo y déjame saber lo que piensas! Estoy abierto a las solicitudes de GitHub, por supuesto.