window.print —— 瀏覽器打印掃盲

博客地址jsonz1993.github.io/2018/06/win…css

github 歡迎start followhtml

近日有個需求是作頁面打印的,趁這個機會補一下比較冷門的瀏覽器打印知識。本文只討論 Chrome、Safari、Firefox瀏覽器的狀況。git

打印接口

首先瀏覽器打印是一個很成熟的應用~ 至少是很早就已經有應用的功能,因此不會有什麼兼容問題github

最簡單的打印就是直接調用 window.print(),固然用 document.execCommand('print') 也能夠達到一樣的效果。json

這時候在Safari和Chrome都會彈起打印預覽的窗口,FireFox沒有預覽而是直接讓你選擇打印機,OSx下能夠經過預覽PDF來預覽~瀏覽器

通常這種直接在網頁上調用 print 的方法是沒辦法知足咱們的業務需求,好比說:app

  • 調整佈局和字體大小來適應A4紙
  • 打印的時候用不一樣的樣式風格
  • 使用更高清的圖片來打印
  • 某一些不相關的東西不出如今打印中等等等等

那麼有哪些方法能夠幫助咱們改善打印的用戶體驗呢?dom

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

咱們能夠在 link 上加上一個 media="print" 來標識這是打印機纔會應用的樣式表, 如:ide

<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

相關文章
相關標籤/搜索