前端打印方法

883 阅读3分钟

前段时间使用到打印的功能,做为 CV 工程师当然是 copy 了很多代码,但很多都有小坑,最后还是自己动手,并整理了一下小坑(留着下次 copy 方便)
打印是通过 **window.print() **方法实现的,打印的内容是当前的页面。但是实际应用过程中打印的东西往往是局部的某一小块儿,这篇文章要介绍的也是局部打印。

法一:取出局部内容放到 body 里

思路:

  1. 获取到需要打印的局部内容
  2. 将局部内容赋 body
  3. 打印 body 内容
  4. 打印完成后给页面重新赋值

代码:

<div id="content">
    <div class="print-box">
      <div class="print-box-image">
        <img [src]=cardData.faceImageUrl class="faceImage" id="print-faceImage">
      </div>
      <ul class="information-box">
        <li class="information-list">
          <span class="list-content-name">{{cardData.idCardName}}</span>
        </li>
        <li class="information-list">
          <span class="list-content-company">{{cardData.company.name}}</span>
        </li>
      </ul>
      <div class="print-box-qr">
        <qr-code [value]="cardData.id + ''" [size]="80"></qr-code>
      </div>
    </div>
  </div>
const initialBody=window.document.body.innerHTML;// 存储当前body中的内容
var printBody= document.getElementById("content").innerHTML;// 要打印的部分
window.document.body.innerHTML= printBody;// 把需要打印的部分赋给body
window.print();// 打印
window.document.body.innerHTML=bdhtml;//重新给页面内容赋值;

样式问题:

正常css里的样式不会在打印纸中显示,正确的打印样式设置姿势如下:

  1. @media print{}

小坑:

// 开始我的操作是这样的,把要打印的部分的 id 直接设置在 print-box 这里,发现样式不生效
<div id="content" class="print-box">
</div>
// 然后改成了这样,样式才生效
<div id="content">
  <div class="print-box">
  </div>
</div>

打印后事件处理问题:

打印后,页面上绑定的事件都失效
解决: ** window.location.reload()** 重新加载页面
但是页面重新加载体验上不是很好,因此,我后面还是选用了加 iframe 的方法

法二:iframe 打印

思路:

  1. 获取到需要打印的局部内容
  2. 创建一个 iframe,并把它添加到 body 中
  3. 把要打印的内容写进 iframe 中
  4. 设置样式

图片加载问题:

页面中的图片往往要通过 http 请求得到,而请求的操作是异步的,因此当完成上面的操作后,打印预览里往往显示不到图片,因此这里需要加一个 iframe.onload 方法,等 iframe 完全加载完成再执行打印。

iframe.onload = function(){
  // 打印
}

代码:

print() {
    const content = document.getElementById("content").innerHTML;
    const iframe = <HTMLInputElement>document.createElement('IFRAME');
    iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;');
    document.body.appendChild(iframe);
    const doc = (<HTMLIFrameElement> <unknown>iframe).contentWindow.document;
    doc.write(content);
    const ys="ul li {list-style: none;}.print-box {width: 300px;margin: 10px auto;border: 1px #5C5C5C solid;}.print-box-image {width: 150px;height: 200px;margin: 20px auto;}.faceImage {width: 150px;height: 200px;}.information-box {margin: 0;padding: 0;text-align: center;}.list-content-name {font-size: 30px;font-weight: 500;}.print-box-qr {margin-bottom: 10px;text-align: center;}";
    const style=document.createElement("style");
    style.innerText=ys;
    doc.getElementsByTagName("head")[0].appendChild(style)
    doc.close();
    iframe.onload = function(){
      (<HTMLIFrameElement> <unknown>iframe).contentWindow.focus();
      (<HTMLIFrameElement> <unknown>iframe).contentWindow.print();
    };      
    return false;
  }