最近由于要求前端生成pdf,就此研究了一阵子,发现就 jspdf 稍微好用一些,为了能导出pdf我试了好几种办法,下面给你们分享一下css
不管使用哪种办法,图片都必须转成base64,不然显示不出来html
这个方法就是把html内容转成canvas,而后生成图片,把图片添加到jspdf里,保存导出pdf前端
display:none
或者visibility:hidden
, 甚至设置定位,top:-1000%
,也不行,会打印出空白的 下面贴出代码// 批量导出多个页面数据在一张pdf里
// html生成Canvas图片,添加到pdf里
downloadPDF () {
// 判断全部图片是否都已经转成base64了,若是没有继续等待
// 我在模板的全部图片的onload里在转base64,每转成一个就调取下载方法,
// 下载方法就判断是否和要生成的图片总数一致
let imgload = this.judgeimg()
if (!imgload) {
return false
}
const pdf = new window.jsPDF('', 'pt', 'a4')
let pdfList = document.getElementsByClassName('pdfItem')
for (let i = 0, len = pdfList.length; i < len; i++) {
let target = pdfList[i]
target.style.background = '#FFFFFF'
window.html2canvas(target, {
dpi: 144, // 设置dpi,会使图片高清一些
onrendered: function (canvas) {
const contentWidth = canvas.width
const contentHeight = canvas.height
//一页pdf显示html页面生成的canvas高度;
const pageHeight = (contentWidth / 595.28) * 841.89
//未生成pdf的html页面高度
let leftHeight = contentHeight
//页面偏移
let position = 0
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
const imgWidth = 595.28
const imgHeight = (592.28 / contentWidth) * contentHeight
const pageData = canvas.toDataURL('image/jpeg', 1.0)
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
// 为下一条数据添加空白页
if (i < len - 1) {
pdf.addPage()
}
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
}
if (i === len - 1) {
pdf.save('PDF存档.pdf')
}
}
})
}
}
复制代码
jsPDF有直接提供html生成PDF的方法,也是对生成的html进行截图生成图片git
display:none
或者visibility:hidden
, 甚至设置定位,top:-1000%
,也不行,会打印出空白的(或者整块黑色的);清晰度通常,不是很高,要求不高的可使用这个方法模板页面的样式必定要设置
background:#ffffff;
,不然会打印出的背景默认黑色github
下面贴出代码canvas
// html直接生成pdf截图
downloadPDF () {
let imgload = this.judgeimg()
if (!imgload) {
return false
}
const pdf = new window.jsPDF('', 'pt', 'a4')
let orderList = document.getElementsByClassName('pdfOrder')
for (let i = 0, len = orderList.length; i < len; i++) {
let target = orderList[i]
target.style.background = '#FFFFFF'
// 经调试,55%的时候内容显示效果比较好,与模板内容样式也有关系,本身调节一下比较好
target.style.width = '55%'
pdf.addHTML(target, function () {
if (i < len - 1) {
pdf.addPage()
}
if (i === len - 1) {
pdf.save('PDF存档.pdf')
}
})
}
}
复制代码
按照jspdf的api逐行编写排版api
既然写出来第三种办法就说明确定是能够解决中文字体不支持状况的, 我查看了jspdf官方网站,没找到api文档。可是搜到了一些文章,而后开始了本身的测试。promise
首先支持设置中文字体的版本,目前找到的方法里,只有1.4.0版本
<script src="https://cdn.bootcss.com/jspdf/1.4.0/jspdf.debug.js"></script>
而后在网上下载一套中文字体,ttf格式的就好。 感谢大佬的生成字体的演示 生成字体代码浏览器
// addFileToVFS方法添加字体文件
doc.addFileToVFS(fileName, Base64content);
// 添加字体
doc.addFont(fileName, fontName, fontStyle);
// 使用字体
doc.setFont(fontName)
复制代码
这里有有个坑,我当时设置了字体样式,而后就乱码了,说明在字体样式上的支持还不是很友好,可是字体大小仍是ok的bash
<button @click="download2PDF" >导出pdf</button>
复制代码
// 手写pdf内容
download2PDF () {
this.pdfloading = true
const pdf = new window.jsPDF()
//添加并设置字体
pdf.addFont('华文仿宋.ttf', 'custom', 'normal');
pdf.setFont('custom');
console.log(this.pdfData.length)
for (let i = 0, len = this.pdfData.length; i < len; i++) {
const item = this.pdfData[i]
try {
const promises = [item.imgurl1, item.imgurl2].map(imgurl => {
return imgGetAction(imgurl)
})
Promise.all(promises).then(values => {
console.log(values)
item.pFrontImg = 'data:image/jpeg;base64,' + btoa(String.fromCharCode(...new Uint8Array(values[0])))
item.pBackImg = 'data:image/jpeg;base64,' + btoa(String.fromCharCode(...new Uint8Array(values[1])))
this.getPdfTemplate(pdf, item)
if (i < len - 1) {
pdf.addPage()
}
if (i === len - 1) {
pdf.save('PDF存档.pdf')
this.pdfloading = false
}
})
} catch (error) {
console.log(error)
this.$message.error('PDF导出失败')
this.pdfloading = false
return false
}
}
},
// pdf模板信息
getPdfTemplate (pdf, data) {
let linePos = 14
pdf.text(60, linePos, '订单号 ' + data.id)
pdf.setFontType('normal')
pdf.setFontSize(10.5)
linePos += 8
//// 信息
pdf.text(15, linePos, '信息')
linePos += 5
pdf.text(15, linePos, '姓名:' + data.name)
pdf.text(75, linePos, '申请日期:' + data.applyDate)
pdf.text(135.5, linePos, '审核日期:' + data.auditDate)
linePos += 5
// 第四行 40 照片
pdf.text(15, linePos, '正面照片:')
pdf.text(75, linePos, '反面照片:')
linePos += 3
pdf.addImage(pFrontImg, 'JPEG', 15, linePos, 50, 60)
pdf.addImage(pBackImg, 'JPEG', 75, linePos, 50, 60)
//// 收取信息 215
linePos += 6
pdf.text(15, linePos, '收取信息')
// 第一行 220
linePos += 5
pdf.text(15, linePos, '收取方式:' + this.wayName[data.receiveWayId])
pdf.text(75, linePos, '收取人姓名:' + data.destName)
pdf.text(135.5, linePos, '收取人联系方式:' + data.destPhone)
// 第二行 225
linePos += 5
let addrStr = (data.destProvince + data.destCity + data.destDistrict + data.destAddress) || '--'
pdf.text(15, linePos, '收货地址:' + addrStr)
//// 结尾footer 230
pdf.text(15, 240, '打印时间:' + formatDate(new Date().valueOf(), 'yyyy-MM-dd hh:mm:ss'))
pdf.text(135.5, 240, '经办人签字:')
}
复制代码
参考内容