最近由於要求前端生成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, '經辦人簽字:')
}
複製代碼
參考內容