对很多中后台的业务来讲,打印场景还是很常见的。针对个人遇到的,以及现有的一些方案对比,总结一波😎(文末有PPT版本,需要留言),希望能帮助同样头疼的你。废话不多说,开讲。
# 一、浏览器打印 # 1、优缺点 通过 window.print() 、document.execCommand('print’) 调用浏览器打印
不同浏览器的区别:在Safari和Chrome都会弹起打印预览的窗口,FireFox(老版本)和 IE 没有预览而是直接让你选择打印机
但是直接使用浏览器打印虽然省事,但是存在很多问题,无法满足我们的打印需求:
1、打印的是整个网页,不能打印局部内容; 2、打印不支持自定义分页行为,默认不支持批量打印; 3、打印的时候样式有问题,所见非所得; 4、打印可以准确识别的样式单位是绝对单位(如pt、mm、cm),对相对单位识别不同打印机可能会得到意想不到的结果; # 2、问题来了 如何实现局部打印?🤔
# (1)innerHtml 简单粗暴,在你不需要考虑体验,项目里面用的也比较少时,可以试试看😆
function innerHtmlPrint(){
// 缓存页面内容
const bodyHtml = window.document.body.innerHTML;
// 获取要打印的dom
const printContentHtml = document.getElementById("print").innerHTML;
// 替换页面内容
window.document.body.innerHTML = printContentHtml;
// 全局打印
window.print();
// 还原页面内容
window.document.body.innerHTML = bodyHtml;
// 页面事件会丢失,需要刷新
window.location.reload();
}
1234567891011121314# (2)iframe 稍微复杂点,需要将打印的内容添加到iframe里,然后打印整个iframe,需要注意:往iframe里写一些样式的时候,一些checkbox,radio要特殊处理。
这里我把项目中用到的iframe局部打印抽出来了,各位可以直接npm使用 vue-iframe-print (opens new window)😎😎😎 插件使用demo (opens new window)
如果你是vue项目,只需要安装后,在需要打印的dom上加上 v-print即可,主要实现原理如下(样式部分省略):
创建iframe 构建iframe docTyp、 head信息 获取局部dom,插入iframe window.print() function onIframePrint(printId) {
const printContentHtml = document.getElementById("printId").innerHTML;
const iframe = document.createElement("iframe");
iframe.setAttribute(
"style",
"position:absolute;width:0px;height:0px;left:-500px;top:-500px;"
);
document.body.appendChild(iframe);
iframe.contentDocument.write(printContentHtml);
iframe.contentDocument.close();
iframe.contentWindow.print();
document.body.removeChild(iframe);
},
1234567891011121314# (3)canvas 将打印内容转为图片,一倍清晰度模糊,可以用2倍canvas。缺点:pdf需要下载,有的产品需求需要一键打印。html2canvas不支持ie,兼容性也是个问题
function print() {
var target = document.getElementsByClassName("right-aside")[0];
target.style.background = "#FFFFFF";
html2canvas(target, {
onrendered:function(canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一页pdf显示html页面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html页面高度
var leftHeight = contentHeight;
//页面偏移
var position = 0;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28/contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new jsPDF('', 'pt', 'a4');
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight );
} else {
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白页
if(leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save("content.pdf");
}
})
}
12345678910111213141516171819202122232425262728293031323334353637383940414243pdf转成图片,会失真,打印一定程度上会模糊,如果用的是针式打印机,打出来的东西基本不能看。👿
也是想了很久找的的解决办法(完美还原):😬😬😬