Javascript 如何延迟加载图像并使其可用于打印

Javascript 如何延迟加载图像并使其可用于打印,javascript,html,image,printing,lazy-loading,Javascript,Html,Image,Printing,Lazy Loading,一些网站有很多图片,因此懒散加载似乎适合减少加载时间和数据消耗。但是,如果您还需要为该网站支持打印,该怎么办 我的意思是,您可以尝试检测打印事件,然后加载图像,如下所示: HTML 注意:如果您在代码游乐场中尝试此操作,请删除DOMContentLoaded事件(或简单地将其分叉为:|) 注意:我并没有为打印前的onbeforeprint和打印后的onafterprint而烦恼 如果缓存了图像,这将正常工作,但这恰恰是而不是关键点。图像应全部加载,然后显示在打印屏幕上 你有什么想法吗?是否有人成

一些网站有很多图片,因此懒散加载似乎适合减少加载时间和数据消耗。但是,如果您还需要为该网站支持打印,该怎么办

我的意思是,您可以尝试检测打印事件,然后加载图像,如下所示:

HTML 注意:如果您在代码游乐场中尝试此操作,请删除
DOMContentLoaded
事件(或简单地将其分叉为:|)

注意:我并没有为打印前的
onbeforeprint
和打印后的
onafterprint
而烦恼

如果缓存了图像,这将正常工作,但这恰恰是而不是关键点。图像应全部加载,然后显示在打印屏幕上

你有什么想法吗?是否有人成功实现了打印就绪的懒散加载插件

更新 我已尝试在检测到打印对话框后将用户重定向到标记版本的网站a.k.a
website.com?print=true
,其中lazyloading被禁用,所有图像正常加载

改进此方法的方法是,在此标记的打印就绪版本的页面中应用
window.print()
方法,在加载完所有图像后打开新的打印对话框,同时在页面顶部显示“wait wait”消息

重要提示:该方法在Chrome中测试过,在Firefox和Edge中都不起作用(因此,这不是答案,而是证据)


它在Chrome中工作,因为当你重定向到另一个网站时,打印对话框关闭(在本例中是相同的url,但有标记)。在Edge和Firefox中,打印对话框是一个实际的窗口,它不会关闭它,这使得它非常不可用。

根据您所需的功能,我不太确定您想做什么是可行的。作为开发人员,我们实际上无法控制用户的浏览器。以下是我对为什么这不完全可能的看法

  • 挂起事件并加载丢失的图像并不能保证图像会从服务器发送到页面中。更具体地说,为打印预览生成的PDF将在图像加载完成之前生成,
    img.src=“…”
    是异步的。不幸的是,
    onbeforeprint
    也会遇到类似的问题。有时有效,有时无效(例如,您的小提琴在safari中测试时有效,但在Chrome中无效)

  • 无法执行打印调用--不能强制浏览器在延迟加载上下文中等待图像加载完成。(我曾经读过一些关于使用警报来实现这一点的文章,但对我来说,它似乎真的很有黑客味,对印刷业的威慑作用大于拖延)

  • 您不能强制
    img.src
    在延迟加载上下文中同步获取该数据。有一些方法可以做到这一点,但它们确实有效,而且可能不会一直有效。我发现

  • 因此,我们有一个问题,如果在打印事件触发时图像未加载,我们无法强制浏览器等待它们完成。当然,我们可以挂接这些图像并将其打印出来,但是如上所述,我们不能等到这些资源加载后打印预览才会弹出

    潜在解决方案(灵感来源于第三点中的链接以及) 您几乎可以通过执行同步XMLHttpRequest逃脱。Synchronous XMLHTTPRequests不允许更改响应类型,它们始终是字符串。但是,您可以将字符串值转换为arrayBuffer,将其编码为base-64编码的字符串,并将src设置为dataURL(请参阅引用巧妙破解的链接)——然而,当我尝试此操作时,我在中遇到了一个错误——因此,如果在理论上正确配置,这是可能的。我很犹豫是否说你可以,因为我无法让小提琴处理以下内容(但这是一条你可以探索的路线!)

    努力提高用户体验 您可以做的是在页面的打印版本中(通过
    @print
    css媒体)显示一些文本,上面写着“图像仍在加载,请取消打印请求并重试”,当图像加载完成后,从DOM中删除“仍在等待资源重试消息”。此外,您还可以将主要内容包装在一个元素中,当内容未加载时,该元素会将显示反转为“无”,因此您只会在“打印预览”对话框中看到该消息

    如果您发布的代码不正确,可能会出现以下情况(请参阅更新):

    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>
    

    我编写了一个延迟加载jquery插件,它支持使用window.onbeforeprint事件和mediaQueryListeners在打印时显示图像。

    我是脚本的作者,最近我开发了一项功能,可以打印所有图像

    已测试跨浏览器,使用的是

    看一看,让我知道你的想法!
    我当然愿意在GitHub上拉取请求。

    你试过了吗嘿!你能澄清一下这个问题吗?你到底在找什么?用户即将打印时延迟加载图像?你能演示一下这个问题吗?@WearyAdventurer我正在寻找一种方法,在用户打开打印对话框时,加载所有未加载的图像,因为它们正在等待加载。这个问题在我提供的任何代码游戏中都有演示,只需在空缓存中按Ctrl+P即可。@IsmailFarooq是的。这是更新中的一个聪明的解决方案;更新后,您是说您无法在Firefox或Edge中调用
    window.print()
    ?还是无法重定向?还是别的什么?抱歉,这可能是直截了当的,我需要一些咖啡!非常完整的答案,如果没有其他人想出什么,你就会得到赏金。无论如何,+1.谢谢,这是一个很好的问题
    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;
    }
    
    .printing-not-ready-message{
      display:none;
    }
    @media print{
      .printing-not-ready-message{
        display:block;
      }
      .do-not-print-content{
        display:none;
      }
    }
    
    <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>
    
    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=""
          }
        }
      })
    });