前言
日常開發中,我們有可能會碰到從系統中導出數據並打印的需要,打印的格式是常規的表格形式,例如:
本文記錄使用js庫html2canvas + jspdf實現html轉PDF、圖片,並下載
畫出頁面
對於我們后端開發人員來說,畫這樣的表格頁面還是比較耗時的,我們可以另辟蹊徑,在word文檔畫好表格,並設置好數據,再另存為html頁面,這樣就得到我們想要的表格頁面
新建一個Word文檔,畫出我們想要的表格格式,其中姓名等信息是程序輸入,備注、簽名等是打印出來后手寫
再另存為HTML文件,查看這個HTML文件的源代碼,注意要復制的代碼
把代碼復制到我們的項目中即可
項目應用
我們是一個vue項目,如何搭建vue項目可以看回我們之前的博客:Vue項目入門實例
首先有個common工具類,封裝引入在線js的方法
/** * common工具類 */ export default { //根據url引入js importJsByUrl(url){ const element = document.createElement("script"); element.src = url; document.body.appendChild(element); }, }
簡單的頁面
<template> <div> <el-row style="text-align: center;"> <el-button v-on:click="pdf">轉PDF</el-button> <el-button v-on:click="img">轉圖片</el-button> </el-row> <div style="display: flex;justify-content: center;"> <div class="app-ccontent"> <!-- 我們復制出來的html代碼就放在這里 --> </div> </div> </div> </template> <script> import CommonUtil from "@/utils/commonUtil.js" export default { data(){ return{ user:{//模擬數據 name:"huanzi-qch", age:"2020年11月", nativePlace:"廣西南寧", nowLiving:"廣東廣州" } } }, created() { //引入 html2canvas、jspdf CommonUtil.importJsByUrl("https://cdn.bootcss.com/html2canvas/0.5.0-alpha2/html2canvas.min.js"); CommonUtil.importJsByUrl("https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js"); }, methods:{ //轉成PDF並下載 pdf(){ }, //轉成圖片並下載 img(){ }, } } </script> <style scoped> .app-ccontent{ padding: 20px; width: 794px; background-color: #eef1f5; } </style>
完整代碼,復制過來的html代碼,最外層的div新增id屬性:id="body" ,方便html2canvas獲取元素內容轉成canvas畫布

<template> <div> <el-row style="text-align: center;"> <el-button v-on:click="pdf">轉PDF</el-button> <el-button v-on:click="img">轉圖片</el-button> </el-row> <div style="display: flex;justify-content: center;"> <div class="app-ccontent"> <div class="Section0" id="body" style="layout-grid:15.6000pt;" > <h2 align=center style="text-align:center;" ><b><span style="mso-spacerun:'yes';font-family:黑體;mso-ascii-font-family:Arial; mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';font-weight:bold; font-size:16.0000pt;mso-font-kerning:1.0000pt;" ><font face="黑體" >導出</font></span></b><b><span style="mso-spacerun:'yes';font-family:黑體;mso-ascii-font-family:Arial; mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';font-weight:bold; font-size:16.0000pt;mso-font-kerning:1.0000pt;" >PDF/<font face="黑體" >圖片測試</font></span></b><b><span style="mso-spacerun:'yes';font-family:Arial;mso-fareast-font-family:黑體; mso-bidi-font-family:'Times New Roman';font-weight:bold;font-size:16.0000pt; mso-font-kerning:1.0000pt;" ><o:p></o:p></span></b></h2><table class=MsoTableGrid border=1 cellspacing=0 style="border-collapse:collapse;width:99.9600%;border:none; mso-border-left-alt:0.5000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;mso-border-insideh:0.5000pt solid windowtext;mso-border-insidev:0.5000pt solid windowtext; mso-padding-alt:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;" ><tr style="height:23.3500pt;" ><td width=24.9800% valign=top style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext; mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >姓名</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=24.9800% valign=top style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >{{user.name}}</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000% valign=top style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >出生年月</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000% valign=top style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >{{user.age}}</span><span style="font-family:Calibri;mso-fareast-font-family:宋體;mso-bidi-font-family:'Times New Roman'; font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td></tr><tr style="height:24.1000pt;" ><td width=24.9800% valign=top style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext; mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >籍貫</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=24.9800% valign=top style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >{{user.nativePlace}}</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000% valign=top style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >現居住</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000% valign=top style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >{{user.nowLiving}}</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td></tr><tr style="height:30.2000pt;" ><td width=24.9800% valign=top style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext; mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-autospace:ideograph-numeric;mso-pagination:none;text-align:center; line-height:700%;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt; mso-font-kerning:1.0000pt;" >備注</span><span style="font-family:宋體;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=75.0000% valign=top colspan=3 style="width:75.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋體;mso-bidi-font-family:'Times New Roman'; font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p> </o:p></span></p><p class=MsoNormal style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋體;mso-bidi-font-family:'Times New Roman'; font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p> </o:p></span></p><p class=MsoNormal style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋體;mso-bidi-font-family:'Times New Roman'; font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p> </o:p></span></p></td></tr><tr style="height:72.7000pt;" ><td width=24.9800% valign=center style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext; mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal align=center style="text-align:center;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';line-height:200%; font-size:12.0000pt;mso-font-kerning:1.0000pt;" >本人確認</span><span style="font-family:Calibri;mso-fareast-font-family:宋體;mso-bidi-font-family:'Times New Roman'; font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=75.0000% valign=center colspan=3 style="width:75.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none; mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext; border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext; mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p> </o:p></span></p><p class=MsoNormal style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >本人已知悉。</span><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋體;mso-hansi-font-family:宋體; mso-bidi-font-family:宋體;line-height:200%;font-size:12.0000pt; mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋體;mso-hansi-font-family:宋體; mso-bidi-font-family:宋體;line-height:200%;font-size:12.0000pt; mso-font-kerning:0.0000pt;" ><o:p> </o:p></span></p><p class=MsoNormal style="text-indent: 192pt;"><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" > </span><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >本人</span><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >簽名:</span><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal ><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋體;mso-hansi-font-family:宋體; mso-bidi-font-family:宋體;line-height:200%;font-size:12.0000pt; mso-font-kerning:0.0000pt;" ><o:p> </o:p></span></p><p class=MsoNormal style="text-indent:270.0000pt;mso-char-indent-count:16.0000;" ><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;margin-right: 30px;" >年</span><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" > </span><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" > </span><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" > </span><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;margin-right: 30px;" >月</span><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" > </span><span style="mso-spacerun:'yes';font-family:宋體;mso-ascii-font-family:仿宋_GB2312; line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >日</span><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal style="text-indent:192.0000pt;mso-char-indent-count:16.0000;" ><span style="font-family:宋體;mso-ascii-font-family:仿宋_GB2312;line-height:200%; font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p> </o:p></span></p></td></tr></table><p class=MsoNormal ><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋體; mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p> </o:p></span></p></div> </div> </div> </div> </template> <script> import CommonUtil from "@/utils/commonUtil.js" export default { data(){ return{ user:{ name:"huanzi-qch", age:"2020年11月", nativePlace:"廣西南寧", nowLiving:"廣東廣州" } } }, created() { //引入 html2canvas、jspdf CommonUtil.importJsByUrl("https://cdn.bootcss.com/html2canvas/0.5.0-alpha2/html2canvas.min.js"); CommonUtil.importJsByUrl("https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js"); }, methods:{ pdf(){ window.html2canvas(document.getElementById("body"), { allowTaint: true, useCORS: true, scale: 2, background: "#eef1f5", }).then(function(canvas) { let contentWidth = canvas.width; let contentHeight = canvas.height; //一頁pdf顯示html頁面生成的canvas高度; let pageHeight = contentWidth / 592.28 * 841.89; //未生成pdf的html頁面高度 let leftHeight = contentHeight; //頁面偏移 let position = 0; //a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高 let imgWidth = 595.28; let imgHeight = 592.28/contentWidth * contentHeight; let pageData = canvas.toDataURL('image/jpeg', 1.0); let pdf = new window.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('exportPdf.pdf'); }) }, img(){ window.html2canvas(document.getElementById("body"), { allowTaint: true, useCORS: true, scale: 2, background: "#eef1f5", }).then((canvas) => { //創建一個隱藏的下載a標簽 let link = document.createElement("a"); link.style.display = "none"; link.setAttribute("download", "exportImg.png"); link.href = canvas.toDataURL('image/png'); document.body.appendChild(link); link.click(); // 執行 <a> 元素的下載 //過河拆橋 link.remove(); }); }, } } </script> <style scoped> .app-ccontent{ padding: 20px; width: 794px; background-color: #eef1f5; } </style>
關鍵代碼
//轉成PDF並下載 pdf(){ window.html2canvas(document.getElementById("body"), { allowTaint: true, useCORS: true, scale: 2, background: "#eef1f5", }).then(function(canvas) { let contentWidth = canvas.width; let contentHeight = canvas.height; //一頁pdf顯示html頁面生成的canvas高度; let pageHeight = contentWidth / 595.28 * 841.89; //未生成pdf的html頁面高度 let leftHeight = contentHeight; //頁面偏移 let position = 0; //a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高 let imgWidth = 595.28; let imgHeight = 595.28/contentWidth * contentHeight; let pageData = canvas.toDataURL('image/jpeg', 1.0); let pdf = new window.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('exportPdf.pdf'); }) }, //轉成圖片並下載 img(){ window.html2canvas(document.getElementById("body"), { allowTaint: true, useCORS: true, scale: 2, background: "#eef1f5", }).then((canvas) => { //創建一個隱藏的下載a標簽 let link = document.createElement("a"); link.style.display = "none"; link.setAttribute("download", "exportImg.png"); link.href = canvas.toDataURL('image/png'); document.body.appendChild(link); link.click(); // 執行 <a> 元素的下載 //過河拆橋 link.remove(); }); },
效果
頁面
下載下來的文件
2021-03-04更新:
問題:當PDF需要分頁時,存在文字被分割的現象
解決:我們首先獲取html轉成PDF后,對應的一頁的高度,然后獲取所有最小的不可被分割的對象(此處為p標簽),遍歷進行高度判斷,當剛好在要被分割,則加一個margin-top把頁面撐開
//處理PDF分頁 var disposeDomList = []; function disposeHtml(){ //一頁pdf顯示html頁面生成的canvas高度 a4紙的尺寸[595.28,841.89] let pageHeight = document.getElementById("body").clientWidth / 595.28 * 841.89; let elementsByTagName = document.getElementsByTagName("p"); for (let i = 0; i < elementsByTagName.length; i++) { let dom = elementsByTagName[i]; let boxHeight = 20; //這里計算高度時,要加上預留的上下邊距(大概20) if (dom.offsetTop % pageHeight + (dom.offsetHeight + boxHeight) >= pageHeight) { let newMarginTop = (dom.offsetHeight + boxHeight * 3) + "px"; console.log(dom); disposeDomList.push({ dom:dom, oldMarginTop:dom.style.marginTop }); dom.style.marginTop = newMarginTop; } } }
使用:
//轉成PDF並下載 function pdf(){ //處理dom disposeHtml(); //省略其他代碼... //html恢復原樣 disposeDomList.forEach(function (value) { value.dom.style.marginTop = value.oldMarginTop; }) }
處理前:
處理中:
找到兩個地方,並設置margin-top
處理后:
后記
轉成PDF后就可以方便的進行打印了;轉成圖片后就方便把文件發給領導看了;nice!
參考文章:
https://segmentfault.com/a/1190000009211079
https://segmentfault.com/a/1190000015820189
https://www.cnblogs.com/xinjie-just/p/13513118.html
https://juejin.cn/entry/6844903586682372109
https://blog.csdn.net/cpongo3/article/details/93623678