跳到主要内容

关于网页打印的一些问题

· 阅读需 8 分钟

有的时候我们需要把web页面进行打印出来,并且要在a4纸上完美呈现,开始的时候我笨打算把网页转换为分页的pdf,这样在本地就可以打印了。

我使用了html2canvas+jspdf这两个神器结合起来来达到我要的效果。

html2canvas是对整个或局部页面进行‘截图’。但这并不是真的截图,而是通过遍历页面DOM结构,收集所有元素信息及相应样式,渲染出canvas image。 简单理解为就是把你想要打印的页面进行渲染成为一张图片了,

使用

使用的API也很简洁,下面代码可以将某个元素渲染成canvas:

html2canvas(element, {
onrendered: function(canvas) {
// canvas is the final rendered <canvas> element
}
});
通过onrendered方法,可以将生成的canvas进行回调,比如插入到页面中:

html2canvas(element, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
想了解更多关于html2canvas的请移步这里

jspdf是一个客户端解决方案生成pdf文件,可以将字体,图片生成pdf,还是很实用的。

文字生成PDF,使用方法如下:

// 默认a4大小,竖直方向,mm单位的PDF
var doc = new jsPDF();

// 添加文本‘Download PDF’
doc.text('Download PDF!', 10, 10);
doc.save('a4.pdf');

图片生成PDF,使用方法如下:

// 三个参数,第一个方向,第二个单位,第三个尺寸格式
var doc = new jsPDF('landscape','pt',[205, 115])

// 将图片转化为dataUrl
var imageData = ‘data:image/png;base64,iVBORw0KGgo...’;

doc.addImage(imageData, 'PNG', 0, 0, 205, 115);
doc.save('a4.pdf');

文字与图片生成PDF,使用方法如下:

// 三个参数,第一个方向,第二个尺寸,第三个尺寸格式
var doc = new jsPDF('landscape','pt',[205, 155])

// 将图片转化为dataUrl
var imageData = ‘data:image/png;base64,iVBORw0KGgo...’;

//设置字体大小
doc.setFontSize(20);

//10,20这两参数控制文字距离左边,与上边的距离
doc.text('Stone', 10, 20);

// 0, 40, 控制文字距离左边,与上边的距离
doc.addImage(imageData, 'PNG', 0, 40, 205, 115);
doc.save('a4.pdf')
想了解更多关于jspdf的请移步这里

html2canvas + jsPDF,使用方法如下:

<script type="text/javascript" src="./js/jsPdf.debug.js"></script>
<script type="text/javascript">
var downPdf = document.getElementById("renderPdf");
downPdf.onclick = function() {
html2canvas(document.body, {
onrendered:function(canvas) {

//返回图片dataURL,参数:图片格式和清晰度(0-1)
var pageData = canvas.toDataURL('image/jpeg', 1.0);

//方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
var pdf = new jsPDF('', 'pt', 'a4');

//addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
pdf.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28/canvas.width * canvas.height );

pdf.save('stone.pdf');

}
})
}
</script>

html2canvas + jsPDF,加上分页效果,使用方法如下:

html2canvas(document.body, {
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');
}
})
以上内容参考地址

这两个前端空间单用起来兼容性都是很好的,但是和在一起就出现一些问题了。使用后在谷歌浏览器下开始是没有问题的但是页面太多就会出现黑页面情况(毕竟我的页面有40多页A4纸大小),在火狐下会出现某一页出现黑页面的现象,在ie下就报错了。 这个方案就被我pass掉了。

后来发现浏览器自带的打印功能,print() 方法用于打印当前窗口的内容。

首先在介绍这个方法之前要要先介绍一个css3的标签,就是@media 查询,一般使用它都是在调整浏览器大小的时候改变样式什么的,看一下他的媒体类型

值                    描述
all 用于所有设备
print 用于打印机和打印预览
screen 用于电脑屏幕,平板电脑,智能手机等。
speech 应用于屏幕阅读器等发声设备

通过这个标签就可以控制打印的时候的纸张大小

@media print {
.bg_page{
width: 297mm;
height: 210mm;
}
}

还要介绍一个属性page-break-after 设置在元素之后进行分页的分页行为

值            描述
auto 默认。如果必要则在元素后插入分页符。
always 在元素后插入分页符。
avoid 避免在元素后插入分页符。
left 在元素之后足够的分页符,一直到一张空白的左页为止。
right 在元素之后足够的分页符,一直到一张空白的右页为止。
inherit 规定应该从父元素继承 page-break-after 属性的设置。

在加上这个属性后就可以调用打印机进行打印了。

@media print {
.bg_page{
width: 297mm;
height: 210mm;
page-break-after:always;
}
}

需要注意的是:如果页面太长,要打印的很多,要是还有一些动画,或者canvas一系列的,需要当页面全部加载完之后,在调用window.print()方法or(Ctrl+p),否则答应出来的页面显示不全,最好是先用可以预览的浏览器进行预览像谷歌这样的,比较好。