近日有個需求是做頁面列印的,趁這個機會補一下比較冷門的浏覽器列印知識。本文隻讨論 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的列印事件。 這裡寫一個簡單的
demofunction 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如需轉載請聯系原作者