web-dev-qa-db-ja.com

画像を遅延読み込みして印刷できるようにする方法

一部のWebサイトには画像がたくさんあるため、読み込み時間とデータ消費量を減らすにはlazyloadingが適しているようです。しかし、そのWebサイトでprintingもサポートする必要がある場合はどうでしょうか。

つまり、あなたは can 印刷イベントを検出してから、次のような画像をロードすることができます:

HTML

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

注:これは、1ピクセルずつのgifダミー画像です。

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

注:コードの遊び場でこれを試す場合は、DOMContentLoadedイベントを削除してください(または単にこれらをフォークしてください: JSFiddle | Codepen )。

注:明らかな理由 のため、onbeforeprintonafterprintでわざわざイベントを行いませんでした=。

これは、画像がキャッシュされている場合は問題なく機能しますが、繰り返しになりますnotポイント。画像がすべて読み込まれ、印刷画面に表示されます。

あなたはなにか考えはありますか?誰かがprint-ready lazyloadingプラグインを正常に実装しましたか?

更新

私は試しましたredirecting印刷ダイアログが検出された後、ユーザーをWebサイトのフラグ付きバージョンa.k.a _website.com?print=true_に移動します。

このメソッドは、このフラグが設定された印刷可能なバージョンのページでwindow.print()メソッドを適用し、すべてのイメージのロードが完了したら新しい印刷ダイアログを開き、 "待機を表示することで改善されていますそれまでの間、 "メッセージがページ上部に表示されます。

重要な注意:このメソッドはChromeでテストされましたが、FirefoxでもEdgeでも機能しません(そのため、これが答えではなく証言である理由)。

Chromeで機能します。別のWebサイトにリダイレクトすると印刷ダイアログが閉じるためです(この場合は同じURLですがフラグが付けられています)。EdgeとFirefoxでは、印刷ダイアログは実際のウィンドウであり、閉じませんそれはかなり使用できなくなります。

24
undefined

あなたが望む機能に基づいて、私があなたがしたいことが実現可能かどうかはよくわかりません。開発者として、ユーザーのブラウザーを実際に制御することはできません。これが完全に可能ではない理由についての私の考えはここにあります。

  1. イベントをフックして行方不明の画像をロードしても、サーバーからページに画像が送られることは保証されません。具体的には、印刷プレビュー用に生成されたPDFは、画像の読み込みが完了する前に生成されます。img.src = "..."は非同期です。同様の問題が発生します。残念ながらonbeforeprintも使用できます。動作することもありますが、動作しないこともあります(例:サファリでテストするとフィドルは動作しましたが、Chromeでは動作しませんでした)

  2. 印刷呼び出しを 停止または停止 することはできません。遅延読み込みコンテキストで画像の読み込みが完了するのをブラウザに待機させることはできません。 (私はこれを達成するためにアラートを使用することについて何かを読みました、しかしそれは私にとって本当にハックであるように見えました、ストールするより印刷することの抑止力の方が多かったです)

  3. 遅延読み込みコンテキストでimg.srcにデータを同期的に取得させることはできません。これを行う方法はいくつかありますが、それらは 巧妙なハックです-純粋な悪 として参照され、常に機能するとは限りません。 同様のアプローチで別のリンクを見つけました

そのため、printイベントが発生するまでに画像が読み込まれない場合、問題が発生するまでブラウザに強制的に待機させることができません。確かに、これらの画像を印刷して取得することはできますが、上記で指摘したように、印刷プレビューがポップアップする前にこれらのリソースが読み込まれるのを待つことはできません。

潜在的な解決策(ポイント3のリンクと this link に触発された)

同期XMLHttpRequestを行うことでほとんど問題はありません。 Syncrhonous XMLHTTPRequestsでは、responseTypeを変更できません。常に文字列です。ただし、文字列値をarrayBufferに変換してbase64エンコードされた文字列にエンコードし、srcをdataURLに設定することもできます(巧妙なハックを参照しているリンクを参照してください)。 jsfiddle -理論的には、正しく構成されていれば可能です。私は次のようにフィドルを動作させることができなかったので、できるとは言えません(しかし、それはあなたが探索できるルートです!)。

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

ユーザーエクスペリエンスを向上させるための回避策

あなたができることは、「@print cssメディアを介して)ページの印刷バージョンにのみ表示されるテキストがあり、「画像はまだ読み込まれています。印刷要求をキャンセルして再試行してください」と画像が終了したときに表示されます。読み込み、DOMから「まだリソースを待っている」というメッセージを削除します。さらに、コンテンツがロードされていないときに表示を反転する要素内にメインコンテンツをラップすることもできるので、表示されるのは印刷プレビューダイアログのメッセージだけです。

これを投稿したコードから離れると、次のようになります(更新された 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

私は Vanilla-lazyload スクリプトの作成者であり、最近、すべての画像の印刷を可能にする機能を開発しました。

this repo code -- live here を使用してクロスブラウザーをテストしました。

見て、あなたの考えを教えてください!もちろん、GitHubでプルリクエストを受け付けています。

3
verlok

Window.onbeforeprintイベントとmediaQueryListenersを使用して印刷時に画像を表示することをサポートする遅延読み込みjqueryプラグインを作成しました。 https://github.com/msigley/Unveil-EX/

1
Chaoix