如何懒惰的加载图像并使其可供打印



有些网站有很多图像,因此 Lazyloading 似乎很适合减少加载时间和数据消耗。但是,如果您还需要支持打印该网站

我的意思是,您 can 尝试检测打印事件,然后加载图像,并用类似的内容:

html

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

注意:这是一个一个像素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,因为明显原因

如果映像被缓存,这将正常工作,但这又是不是的点。图像/s应全部加载,然后出现在打印屏幕中。

您有什么想法吗?是否有人成功实现了打印 Lazyloading插件?

更新

我已经尝试了重定向在检测到"打印对话框"后,用户转到网站的标记版本A.K.A website.com?print=true,其中lazyloading被停用了,所有图像正常加载。

通过在此页面的标记打印版本中应用window.print()方法,可以改善此方法,一旦所有图像完成加载,打开一个新的打印对话框,并显示"等待">在页面顶部的同时。

重要说明:此方法在Chrome中进行了测试,它在Firefox和Edge中不起作用(因此,为什么这不是答案,而是证词(。

重定向到另一个网站时,它在Chrome BeaCuse中工作(在这种情况下是相同的URL,但标记为标记(。在Edge和Firefox中,打印对话框是一个实际的窗口,它不会关闭它,使其非常无法使用。

基于您所需的功能,我不确定您想做什么是可行的。作为开发人员,我们实际上并没有控制用户浏览器。这是我关于为什么不可能完全可能的想法。

  1. 挂接事件以进行并加载您的缺失图像不能保证您的图像将从服务器中添加到页面中。更具体地说,为您的打印预览生成的PDF将在完成图像加载之前生成,img.src = "..."是异步的。不幸的是,您也遇到了onbeforeprint的类似问题。有时它有效,有时它不行(例如,在野生动物园进行测试时,您的小提琴工作起作用,但不在Chrome中(

  2. 您不能停滞不见或停止打印呼叫 - 您不能强迫浏览器等待图像在懒惰的加载上下文中完成加载。(我读过一些有关使用警报来实现这一目标的东西,但对我来说似乎真的很骇人听闻,而不是停滞不前(

  3. 您不能强迫img.src在懒惰的上下文中同步获取该数据。有一些方法可以做到这一点,但它们是聪明的骇客 - 被称为纯粹的邪恶,可能永远不会起作用。我找到了另一种类似方法的链接

因此,我们有问题,如果未通过触发时间打印事件加载图像,我们将无法迫使浏览器等到完成。当然,我们可以连接并去印刷这些图像,但是如上所述,我们迫不及待地等待这些资源在打印预览弹出之前加载。

潜在解决方案(受第三点以及此链接中的链接的启发(

您几乎可以逃脱同步的XMLHTTPRequest。Syncrhonous XMLHTTPRequeSts不会让您更改响应类型,它们始终是字符串。但是,您可以将字符串值转换为arraybuffer将其编码为基本-64编码的字符串,然后将SRC设置为dataUrl(请参阅引用巧妙hacks的链接( - 但是,当我尝试此操作时,我会在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=""
      }
    }
  })
});

我是Vanilla-Lazyload脚本的作者,我最近开发了一项功能,使所有图像的打印成为可能!

使用此存储量代码测试的交叉浏览器。

看一看,让我知道您的想法!我当然可以在GitHub上提取请求。

我写了一个懒惰的加载jQuery插件,该插件支持使用窗口显示在打印上显示图像。和MediaQueryListeners。https://github.com/msigley/unveil-ex/

//declare custom onbeforeprint method
const customOnBeforePrint = () => {
    const smoothScroll = (h) => {
        let i = h || 0;
        if (i < 200) {
            setTimeout(() => {
                window.scrollTo(window.scrollY, window.scrollY + i);
                smoothScroll(i + 10);
            }, 10);
        }
    };
    let height = document.body.scrollHeight;
    let newHeight;
    while (true) {
        smoothScroll(100);
        if (newHeight === height) break;
        height = newHeight;
    }
};
//override the onbeforeprint method
window.onbeforeprint = customOnBeforePrint;

复制该粘贴到DevTool的控制台,然后尝试单击"打印"按钮。那个解决方法对我有用。

对于与我在同一条船上的人:使用浏览器本机loading="lazy"时,您可以简单地删除该属性当打印发生时。以下是我的jQuery实施。

window.onbeforeprint = function () {
  $('img').each(function () {
    $(this).removeAttr('loading')
  });
}

Chrome然后将加载所有图像,它们在打印时会显示。

最新更新