需求场景
将页面指定的区域转PDF并调用打印机,生成的PDF是横向分页
技术栈:Vue、Element、html2Canvas、jspdf、print-js
实现步骤
插件安装好的前提:
页面通过html2Canvas生成图片 —— jspdf转PDF —— print-js调用打印机
安装插件
这里主要说html2Canvas、jspdf、print-js
npm install print-js --save
npm install html2canvas --save
页面引入插件
import html2Canvas from "html2canvas";
import JsPDF from "jspdf";
<!-- 需要转换的页面 -->
<div class="partbox partbox2" id="pdfDom" ref="pdfDom"></div>
// 调用转图片页面处理方法
handlePrint() {
this.getPdfFromHtml(this.$refs.pdfDom, "pdf-name")
},
// 可设置页边距,滚动有影响,需要设置滚动置顶
getPdfFromHtml(ele, pdfFileName) {
//导出后的文件名称pdfFileName
pdfFileName = pdfFileName || 'pdf'
// 页面先滚动到顶部,不然截取的pdf样式会有问题
document.body.scrollTop = document.documentElement.scrollTop = 0;
html2Canvas(ele, {
dpi: window.devicePixelRatio * 4, //将分辨率提高到特定的DPI 提高四倍
// scale: 4, //按比例增加分辨率
logging: false, //日志开关,便于查看html2canvas的内部执行流程
scale: 4,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
allowTaint: false,
scrollY: 0,
scrollX: 0,
height: ele.offsetHeight,
width: ele.offsetWidth,
backgroundColor: '#fff',
}).then(canvas => {
const _this = this;
//未生成pdf的html页面高度
var leftHeight = canvas.height;
var a4Width = 801.89 // 原A4宽 592 因为要设置边距 20 ,这里要减掉 40
var a4Height = 552.28 // 原A4高 841 因为要设置边距 20 ,这里要减掉 40
//一页pdf显示html页面生成的canvas高度;
var a4HeightRef = Math.floor(canvas.width / a4Width * a4Height);
//pdf页面偏移
var position = 0;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
let myfile1 = _this.dataURLtoFile(pageData, pdfFileName + '.jpg')
//生成图片
const formData1 = new FormData()
/*
// 页面生成的图片,这里是为了查看生成的图片是否偏移等问题检测
formData1.append('file', myfile1)
_this.$axios.post(`${_this.$Tools.Conts.domain}uploads`, formData1).then(res => {
if (res.data.code == 0) {
console.log(res.data.data.src)
window.open(res.data.data.src)
}
})*/
//图片转pdf
// 图片转pdf的大小
var pdf = new JsPDF('l', 'pt', '[801.89, 552.28]');
// var pdf = new JsPDF('l', 'pt', 'a4');
var index = 1,
canvas1 = document.createElement('canvas'),
height;
pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');
function createImpl(canvas) {
if (leftHeight > 0) {
index++;
var checkCount = 0;
if (leftHeight > a4HeightRef) {
var i = position + a4HeightRef;
for (i = position + a4HeightRef; i >= position; i--) {
var isWrite = true
for (var j = 0; j < canvas.width; j++) {
var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
isWrite = false
break
}
}
if (isWrite) {
checkCount++
if (checkCount >= 10) {
break
}
} else {
checkCount = 0
}
}
height = Math.round(i - position) || Math.min(leftHeight, a4HeightRef);
if (height <= 0) {
height = a4HeightRef;
}
} else {
height = leftHeight;
}
canvas1.width = canvas.width;
canvas1.height = height;
var ctx = canvas1.getContext('2d');
ctx.drawImage(canvas, 0, position, canvas.width, height, 0, 0, canvas.width, height); // 边距这里设置0,不然又黑边
if (position != 0) {
pdf.addPage();
}
// 设置 20px 边距
pdf.addImage(canvas1.toDataURL('image/jpeg', 1.0), 'JPEG', 20, 30, a4Width,
a4Width / canvas1.width * height);
leftHeight -= height;
position += height;
if (leftHeight > 0) {
setTimeout(createImpl, 500, canvas);
} else {
// 需求1:文件保存到本地
//pdf.save(pdfFileName + '.pdf')
// 需求2:将pdf文件上传到服务器,服务器返回链接,也可以直接保存到本地
let buffer = pdf.output("datauristring")
let myfile = _this.dataURLtoFile(buffer, pdfFileName + '.pdf')
const formData = new FormData()
formData.append('file', myfile)
_this.$axios.post(`${_this.$Tools.Conts.domain}uploads`, formData).then(
res => {
if (res.data.code == 0) {
// 生成的pdf链接
console.log(res.data.data.src)
// 调用本地打印机
_this.$print({
printable: res.data.data.src,
type: 'pdf'
})
} else {
_this.$message({
message: res.data.message,
type: "warning"
});
}
})
}
}
}
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < a4HeightRef) {
pdf.addImage(pageData, 'JPEG', 20, 30, a4Width, a4Width / canvas.width * leftHeight);
//直接保存到本地
// pdf.save(pdfFileName + '.pdf')
// 上传到服务器
let buffer = pdf.output("datauristring")
// // 将base64格式的字符串转换为file文件
let myfile = _this.dataURLtoFile(buffer, pdfFileName + '.pdf')
const formData = new FormData()
formData.append('file', myfile)
_this.$axios.post(`${_this.$Tools.Conts.domain}uploads`, formData).then(
res => {
if (res.data.code == 0) {
console.log(res.data.data.src)
// 调用本地打印机
_this.$print({
printable: res.data.data.src,
type: 'pdf'
})
} else {
_this.$message({
message: res.data.message,
type: "warning"
});
}
})
} else {
try {
pdf.deletePage(0);
setTimeout(createImpl, 500, canvas);
} catch (err) {
console.log(err);
}
}
})
}
生成图片: