博客地址jsonz1993.github.io/2018/06/win…css
近日有個需求是作頁面打印的,趁這個機會補一下比較冷門的瀏覽器打印知識。本文只討論 Chrome、Safari、Firefox瀏覽器的狀況。git
首先瀏覽器打印是一個很成熟的應用~ 至少是很早就已經有應用的功能,因此不會有什麼兼容問題github
最簡單的打印就是直接調用 window.print()
,固然用 document.execCommand('print')
也能夠達到一樣的效果。json
這時候在Safari和Chrome都會彈起打印預覽的窗口,FireFox沒有預覽而是直接讓你選擇打印機,OSx下能夠經過預覽PDF來預覽~瀏覽器
通常這種直接在網頁上調用 print 的方法是沒辦法知足咱們的業務需求,好比說:app
那麼有哪些方法能夠幫助咱們改善打印的用戶體驗呢?dom
咱們能夠在 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
,分別表示打印事件觸發先後。 這個事件在 IE6 就已經支持了,不過一點都不驚訝~ 畢竟IE很早就支持不少接口調用,以前好像作過IE打開Excel的需求~ 兼容大概是 Firefox、IE全支持, Chrome63+支持, Safari暫不支持,算是一半一半吧。
window.addEventListener('beforeprint', ()=> {
document.body.innerHTML = '正在打印...';
});
window.addEventListener('afterprint', ()=> {
document.body.innerHTML = '打印完成...';
});
複製代碼
若是你想要兼容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'));
複製代碼
最後一些注意的事情
<header>
裏面的參考: