html2Canvas+JsPDF
最初使用了html2Canvas+JsPDF这个方案,其实就是把页面转成了canvas变成图片然后再使用jspdf像拍照一样拍下来。 缺点:帧数不高,会造成内容截断 代码:
/**
* html To pdf
* @param query object
*/
export function html2Pdf (query) {
const { ele, eleW, eleH, eleOffsetTop, eleOffsetLeft, title } = query
var canvas = document.createElement('canvas')
var abs = 0
let Winin = document.documentElement.clientWidth || document.body.clientWidth // 获得当前可视窗口的宽度(不包含滚动条)
let Winout = window.innerWidth // 获得当前窗口的宽度(包含滚动条)
if (Winout > Winin) {
// abs = (win_o - win_i)/2; // 获得滚动条长度的一半
abs = (Winout - Winin) / 2 // 获得滚动条宽度的一半
}
let scale = 2
canvas.width = eleW * scale // 将画布宽&&高放大两倍
canvas.height = eleH * scale
var context = canvas.getContext('2d')
context.scale(scale, scale) // 2,2
context.translate(-eleOffsetLeft - abs, -eleOffsetTop)
// 这里默认横向没有滚动条的情况,因为offset.left(),有无滚动条的时候存在差值,因此
// translate的时候,要把这个差值去掉
const options = {
dpi: 300,
scale,
width: eleW,
height: eleH,
backgroundColor: '#ffffff',
useCORS: true // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
}
html2Canvas(ele, options).then((canvas) => {
// var contentWidth = canvas.width
// var contentHeight = canvas.height
// a4纸的尺寸[592.28,841.89]
const A4_WIDTH = 592.28
const A4_HEIGHT = 841.89
// 一页pdf显示html页面生成的canvas高度;
var pageHeight = eleW / A4_WIDTH * A4_HEIGHT
// 未生成pdf的html页面高度
var leftHeight = eleH
// 页面偏移
var position = 0
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = A4_WIDTH
var imgHeight = A4_HEIGHT / eleW * eleH
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', 左,上,宽度,高度)设置在pdf中显示;
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
// pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
} else { // 分页
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= A4_HEIGHT
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
}
// 可动态生成
pdf.save(title + '.pdf')
})
}
使用浏览器自带的window+@media媒体查询+css属性page-break-inside: avoid;
在需要单独一页的地方添加上 page-break-inside: avoid; 不需要的属性或者要在打印的时候做操作可以媒体查询监听print
例如:
<div class="no-print">不需要打印</div>
<div class="view">我需要单独占满一页A4</div>
css:
@media print {
.no-print {
display: none;
},
.view {
page-break-inside: avoid;
}
}
目前本人项目都是使用的这个方案比较香