web-dev-qa-db-fra.com

Comment charger paresseux des images et les rendre disponibles pour impression

Certains sites Web contiennent de nombreuses images, donc lazyloading semble approprié pour réduire les temps de chargement et la consommation de données. Mais que se passe-t-il si vous devez également prendre en charge printing pour ce site Web?

Je veux dire, vous pouvez essayez de détecter l'événement d'impression, puis chargez les images, avec quelque chose comme ceci:

HTML

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

Note: Ceci est une image factice gif de pixels, un par un.

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';
    }
  })
});

Remarque: si vous essayez ceci dans un code, supprimez l'événement DOMContentLoaded (ou branchez simplement: JSFiddle | Codepen ).

_ {Note: Je n'ai pas été dérangé par les onbeforeprint et onafterprint pour raisons évidentes .

Cela fonctionnera correctement si l'image est mise en cache, mais là encore c'est précisément pas le point. La/les image (s) doivent toutes se charger puis apparaître sur l'écran d'impression.

Avez-vous des idées? Quelqu'un at-il implémenté avec succès un plugin print-ready lazyloading?

Mettre à jour

Une fois la boîte de dialogue d'impression détectée, j'ai essayé redirectant après l'avoir détectée dans une version signalée du site Web a.k.a website.com?print=true où lazyloading est désactivée et où toutes les images se chargent normalement.

Cette méthode est améliorée en appliquant la méthode window.print() dans cette version imprimée de la page, prête à imprimer, en ouvrant une nouvelle boîte de dialogue d'impression une fois le chargement de toutes les images terminé et en affichant un message "attendez" entre-temps. en haut de la page.

Note importante: cette méthode a été testée sur Chrome, elle ne fonctionne ni dans Firefox, ni dans Edge (par conséquent, ce n'est pas une réponse, mais un témoignage).

Cela fonctionne dans Chrome parce que la boîte de dialogue d'impression se ferme lorsque vous redirigez vers un autre site Web (dans ce cas, la même URL, mais marquée). Dans Edge et Firefox, la boîte de dialogue d'impression est une fenêtre réelle et ne la ferme pas, ce qui la rend inutilisable.

23
undefined

En fonction de vos fonctionnalités souhaitées, je ne suis pas sûr que ce que vous voulez faire soit réalisable. En tant que développeur, nous ne contrôlons pas vraiment le navigateur des utilisateurs. Voici pourquoi je pense que ce n'est pas possible.

  1. Organiser l’événement pour charger vos images manquantes ne vous garantira pas que les images seront transférées du serveur dans votre page. Plus spécifiquement, le PDF généré pour votre aperçu avant impression sera généré avant le chargement de vos images, le img.src = "..." est asynchrone. Malheureusement, vous rencontriez des problèmes similaires avec onbeforeprint. Parfois, cela fonctionne, parfois non (par exemple, votre violon a fonctionné lors de tests dans Safari, mais pas dans Chrome).

  2. Vous ne pouvez pas caler ou arrêter l'appel à imprimer - vous ne pouvez pas forcer le navigateur à attendre que votre image se termine dans le contexte de chargement paresseux. (J'ai lu quelque chose à propos de l'utilisation des alertes pour y parvenir une fois, mais cela me semblait vraiment bidon, était plus dissuasif pour l'impression que pour le blocage)

  3. Vous ne pouvez pas forcer img.src à obtenir ces données de manière synchrone dans un contexte de chargement différé. Il existe certaines méthodes pour ce faire, mais elles sont des hacks intelligents - référencées comme du pur mal et peuvent ne pas fonctionner dans tous les cas. J'ai trouvé un autre lien avec une approche similaire

Nous avons donc un problème. Si les images ne sont pas chargées avant le moment où l'événement d'impression est déclenché, nous ne pouvons pas forcer le navigateur à attendre qu'elles soient terminées. Bien sûr, nous pouvons accrocher et imprimer ces images, mais comme indiqué ci-dessus, nous ne pouvons pas attendre que ces ressources se chargent avant que l'aperçu avant impression ne s'affiche.

Solution potentielle (inspirée par les liens au point trois ainsi que ce lien )

Vous pourriez presque vous en sortir en faisant un XMLHttpRequest synchrone. Les syntaxes XMLHTTPRequests synchronisées ne vous permettront pas de changer le responseType, elles sont toujours des chaînes. Cependant, vous pouvez convertir la valeur de chaîne en arrayBuffer en une chaîne codée en base 64 et définir la src sur une dataURL (voir le lien référençant des hacks intelligents). le jsfiddle - donc ce serait possible, si les choses étaient configurées correctement, en théorie. J'hésite à dire que oui, car je n'ai pas réussi à faire fonctionner le violon avec ce qui suit (mais c'est un itinéraire que vous pouvez explorer!).

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;
}

Contourner pour améliorer l'expérience utilisateur

Ce que vous pouvez faire, c’est que le texte qui s'affiche uniquement dans la version imprimée de votre page (via le support @print css) indique que les images sont en cours de chargement, annulez votre demande d’impression et réessayez. "toujours en attente de ressources, réessayez message" du DOM. Plus loin, vous pouvez envelopper votre contenu principal dans un élément qui inverse l'affichage en aucun lorsque le contenu n'est pas chargé. Vous ne voyez donc que ce message dans la boîte de dialogue d'aperçu avant impression.

En sortant du code que vous avez posté, cela pourrait ressembler à quelque chose comme ce qui suit (voir mis à jour jsfiddle ):

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=""
      }
    }
  })
});
13
Arthur Weborg

Je suis l'auteur du script Vanilla-lazyload et j'ai récemment développé une fonctionnalité qui permet d'imprimer toutes les images! 

Test croisé navigateur en utilisant ce code de repo qui est vivre ici .

Jetez un coup d'œil et dites-moi ce que vous en pensez! ... Je suis ouvert aux demandes sur GitHub, bien sûr.

1
verlok

J'ai écrit un plug-in de chargement paresseux jquery qui permet d'afficher des images sur papier à l'aide des événements window.onbeforeprint et de mediaQueryListeners . https://github.com/msigley/Unveil-EX/

0
Chaoix