天天看點

window.print —— 浏覽器列印掃盲

近日有個需求是做頁面列印的,趁這個機會補一下比較冷門的浏覽器列印知識。本文隻讨論 Chrome、Safari、Firefox浏覽器的情況。

列印接口

首先浏覽器列印是一個很成熟的應用~ 至少是很早就已經有應用的功能,是以不會有什麼相容問題

最簡單的列印就是直接調用

window.print()

,當然用

document.execCommand('print')

也可以達到同樣的效果。

這時候在Safari和Chrome都會彈起列印預覽的視窗,FireFox沒有預覽而是直接讓你選擇列印機,OSx下可以通過預覽PDF來預覽~

一般這種直接在網頁上調用 print 的方法是沒辦法滿足我們的業務需求,比如說:

  • 調整布局和字型大小來适應A4紙
  • 列印的時候用不同的樣式風格
  • 使用更高清的圖檔來列印
  • 某一些不相關的東西不出現在列印中等等等等

那麼有哪些方法可以幫助我們改善列印的使用者體驗呢?

使用 print style sheet (列印樣式表)

我們可以在 link 上加上一個 media="print" 來辨別這是列印機才會應用的樣式表, 如:

<link href="/example.css" media="print" rel="stylesheet" />
複制代碼           

這樣列印的時候,就會預設将該樣式表應用到文檔中

使用媒介查詢

相容性: IE9+ 其他主流浏覽器都支援

當我們要修改的樣式沒有那麼多的時候,其實完全不需要重新寫個樣式表,隻要寫上一個媒介查詢也可以達到同樣的效果,如:

h1 {
  font-size: 14px;
}
@media print {
  h1 {
    font-size: 20px;
  }
}
複制代碼           

事件監聽

beforeprint && afterprint

有兩個事件可以監聽到到列印事件,一個是

beforeprint

,一個是

afterprint

,分别表示列印事件觸發前後。

這個事件在 IE6 就已經支援了,不過一點都不驚訝~ 畢竟IE很早就支援很多接口調用,之前好像做過IE打開Excel的需求~

相容大概是 Firefox、IE全支援, Chrome63+支援, Safari暫不支援,算是一半一半吧。

window.addEventListener('beforeprint', ()=> {
  document.body.innerHTML = '正在列印...';
});
window.addEventListener('afterprint', ()=> {
  document.body.innerHTML = '列印完成...';
});
複制代碼           

window.matchMedia 測試媒體查詢接口

如果你想要相容Safari或許可以試一下

window.matchMedia

相容是 IE10+,其他主流浏覽器完全沒問題。

這個的用法稍微有點不一樣,首先建立一個MediaQueryList對象,再通過他監聽變化,如:

const printMedia = window.matchMedia('print');
function printChange({ matches, }) {
  document.body.innerHTML = matches? '正在列印...': '列印完成/取消';
}
printMedia.addListener(printChange);
複制代碼           

更加個性化定制列印區域/列印内容

如果項目上用的是jq等,或者想簡單粗暴的列印某個區域又不想重新寫樣式表啊,什麼的。

最傻瓜版的方式就是直接用jq插件

jQuery.print

也可以自己寫一個去處理,大概的思路是建立一個iframe,把要列印的dom和樣式表都丢進去,再調用iframe的列印事件。 這裡寫一個簡單的

demo
function printPartial(dom, { title= document.title,}= {}) {
  if (!dom) return;
  let copyDom = document.createElement('span');
  const styleDom = document.querySelectorAll('style, link, meta');
  const titleDom = document.createElement('title');
  titleDom.innerText = title;

  copyDom.appendChild(titleDom);
  Array.from(styleDom).forEach(item=> {
    copyDom.appendChild(item.cloneNode(true));
  });
  copyDom.appendChild(dom.cloneNode(true));

  const htmlTemp = copyDom.innerHTML;
  copyDom = null;

  const iframeDom = document.createElement('iframe');
  const attrObj = {
    height: 0,
    width: 0,
    border: 0,
    wmode: 'Opaque'
  };
  const styleObj = {
    position: 'absolute',
    top: '-999px',
    left: '-999px',
  };
  Object.entries(attrObj).forEach(([key, value])=> iframeDom.setAttribute(key, value));
  Object.entries(styleObj).forEach(([key, value])=> iframeDom.style[key] = value);
  document.body.insertBefore(iframeDom, document.body.children[0]);
  const iframeWin = iframeDom.contentWindow;
  const iframeDocs = iframeWin.document;
  iframeDocs.write(`<!doctype html>`);
  iframeDocs.write(htmlTemp);
  iframeWin.focus();
  iframeWin.print();
  document.body.removeChild(iframeDom);
}

printPartial(document.querySelector('#description'));
複制代碼           

最後一些注意的事情

  • 列印會列印document下所有可見元素, 包括

    <header>

    裡面的
  • 背景都不會被列印出來,包括背景色啊背景圖檔啊等等
  • 如果圖檔是懶加載的,需要特殊處理,不然列印的時候會直接空白

參考:

blog.csdn.net/fengshuiyue… Mozilla print Mozilla Using_a_print_style_sheet

原文釋出時間為:2018年06月30日

作者:Jsonz

本文來源:

掘金 https://juejin.im/post/5b371a8a6fb9a00e5326f06c

如需轉載請聯系原作者

繼續閱讀