前端實(shí)現(xiàn)HTML網(wǎng)頁(yè)轉(zhuǎn)PDF并導(dǎo)出
有個(gè)新需求,當(dāng)點(diǎn)擊【下載】按鈕時(shí),直接將當(dāng)前 html頁(yè)面下載為 PDF。通過(guò) html2canvas + jsPDF 可實(shí)現(xiàn)PDF單頁(yè)下載,甚至是多頁(yè)下載,記錄分享一下~ 最后有源碼,可自取
html2canvas
html2canvas官網(wǎng)在這:html2canvas - Screenshots with JavaScript
html2canvas 是一個(gè) HTML 渲染器。該腳本允許你直接在用戶瀏覽器截取頁(yè)面或部分網(wǎng)頁(yè)的“屏幕截屏”,通過(guò)讀取 DOM 以及應(yīng)用于元素的不同樣式,將當(dāng)前頁(yè)面呈現(xiàn)為 canvas
圖像
安裝 html2canvas
npm install --save html2canvas
截取頁(yè)面生成canvas
,并將其插入頁(yè)面中
html2canvas(document.body}).then(function(canvas) { document.body.appendChild(canvas); });
注意:受限于瀏覽器的實(shí)現(xiàn),HTML 的 canvas 元素也有高度限制 可參考 canvas 最大畫布尺寸 - MDN
- Chrome 和 Firefox 等現(xiàn)代瀏覽器,canvas 的最大尺寸通常限制在 32767 像素,這也是 WebGL 和 2D canvas 的共同限制。超過(guò)這個(gè)值會(huì)導(dǎo)致 canvas 生成失敗,拋出錯(cuò)誤,或者顯示空白內(nèi)容。
- 老版本的 IE 對(duì) canvas 尺寸限制較為嚴(yán)格,一般在 8192 像素上下?,F(xiàn)代版本的 Edge 則與 Chrome 的限制類似
jsPDF
jsPDF文檔可以看這:GitHub - parallax/jsPDF: Client-side JavaScript PDF generation for everyone.
安裝 jspdf
npm install jspdf --save
API也很簡(jiǎn)單,下面是個(gè)生成文本和圖片的PDF樣例
// jsPDF 下載文本圖片PDF const downLoadPdf = () => { // 三個(gè)參數(shù),第一個(gè)方向,第二個(gè)單位,第三個(gè)尺寸 'a4' = [595.28,841.89] const doc = new jsPDF('', 'pt', [500, 1000]) // 字體大小 doc.setFontSize(50) // 文本,左邊距,上邊距 doc.text('Hello world!', 10, 50) // base64,圖片類型,左邊距,上邊距,寬度,高度 doc.addImage(base64, 'PNG', 10, 60, 400, 200) doc.save('a4.pdf') }
注意: jsPDF 生成的 PDF 默認(rèn)以 pt (point) 為單位,單頁(yè)的最大高度通常限制在 14400 pt。超過(guò)這個(gè)高度可能導(dǎo)致生成的 PDF 無(wú)法正確渲染或?yàn)g覽器崩潰?
html2canvas + jsPDF 實(shí)現(xiàn)頁(yè)面下載
單頁(yè)下載(自適應(yīng)紙)
PDF頁(yè)面的寬高 采用 canvas的寬高
- 若
canvas.height >= canvas.width
,采用portrait
縱向頁(yè)面 - 若
canvas.width > canvas.height
,采用landscape
橫向頁(yè)面
如果頁(yè)面很長(zhǎng)的話,單頁(yè)下載就會(huì)生成一張長(zhǎng)長(zhǎng)的PDF。注意!超過(guò)限制就會(huì)顯示空白頁(yè)面, jsPDF 生成的 PDF單頁(yè)最大高度為 14400pt
canvas也有最大高度限制 32767像素,如果頁(yè)面過(guò)長(zhǎng)的話,通過(guò) html2canvas 生成 canvas會(huì)失敗
const downLoadPdfAutoSingle = () => { html2canvas(document.body, { scale: window.devicePixelRatio * 2, // 使用設(shè)備的像素比 * 2 }).then(canvas => { // 返回圖片dataURL,參數(shù):圖片格式和清晰度(0-1) const pageData = canvas.toDataURL('image/jpeg', 1.0) const pageWidth = canvas.width const pageHeight = canvas.height const orientation = canvas.height >= canvas.width ? 'portrait' : 'landscape' // portrait 表示縱向,landscape表示橫向 const pdf = new jsPDF(orientation, 'pt', [pageWidth, pageHeight]) // addImage后兩個(gè)參數(shù)控制添加圖片的尺寸,此處將頁(yè)面高度按照a4紙寬高比列進(jìn)行壓縮 pdf.addImage( pageData, 'JPEG', 0, 0, pageWidth, pageHeight ) pdf.save('下載一頁(yè)P(yáng)DF(自適應(yīng)紙).pdf') }) }
單頁(yè)下載(A4紙)
已知:A4紙的寬度 和 canvas的寬度高度??傻?canvas在A4紙上占用的總高度(A4紙尺寸為寬 595.28pt,高 841.89pt)
如果頁(yè)面很長(zhǎng)的話,單頁(yè)下載就會(huì)生成一張長(zhǎng)長(zhǎng)的PDF。注意!超過(guò)限制就會(huì)顯示空白頁(yè)面, jsPDF 生成的 PDF單頁(yè)最大高度為 14400pt
canvas也有最大高度限制 32767像素,如果頁(yè)面過(guò)長(zhǎng)的話,通過(guò) html2canvas 生成 canvas會(huì)失敗
const downLoadPdfA4Single = () => { html2canvas(document.body).then(canvas => { // 返回圖片dataURL,參數(shù):圖片格式和清晰度(0-1) const pageData = canvas.toDataURL('image/jpeg', 1.0) // 方向縱向,尺寸ponits,紙張格式 a4 即 [595.28, 841.89] const A4Width = 595.28 const A4Height = 841.89 // A4紙寬 const pageHeight = A4Height >= A4Width * canvas.height / canvas.width ? A4Height : A4Width * canvas.height / canvas.width const pdf = new jsPDF('portrait', 'pt', [A4Width, pageHeight]) // addImage后兩個(gè)參數(shù)控制添加圖片的尺寸,此處將頁(yè)面高度按照a4紙寬高比列進(jìn)行壓縮 pdf.addImage( pageData, 'JPEG', 0, 0, A4Width, A4Width * canvas.height / canvas.width, ) pdf.save('下載一頁(yè)P(yáng)DF(A4紙).pdf') }) }
多頁(yè)下載(自適應(yīng)紙)
由于 jsPDF 單頁(yè)最大高度的限制 又或是 需求層面,我們需要實(shí)現(xiàn)自動(dòng)分頁(yè)下載
我們?cè)O(shè)置一頁(yè)P(yáng)DF頁(yè)面寬度為canvas.width
,高度為canvas.width * 1.3
分頁(yè)思路:每個(gè)PDF頁(yè)面都顯示一張 canvas 圖,只不過(guò)是計(jì)算偏移量,每個(gè)PDF頁(yè)面顯示的是 canvas 的不同位置
問(wèn)題來(lái)了,如何創(chuàng)建一個(gè)新的PDF頁(yè)面呢?可以使用 jsPDF 的pdf.addPage()
const downLoadPdfAutoMultiple = () => { const ele = document.body html2canvas(ele, { scale: window.devicePixelRatio * 2, // 使用設(shè)備的像素比 * 2 }).then(canvas => { let position = 0 //頁(yè)面偏移 const autoWidth = canvas.width // 一頁(yè)紙寬度 const autoHeight = canvas.width * 1.3 // 一頁(yè)紙高度 // 一頁(yè)P(yáng)DF可顯示的canvas高度 const pageHeight = (canvas.width * autoHeight) / autoWidth // 未分配到PDF的canvas高度 let unallottedHeight = canvas.height // canvas對(duì)應(yīng)的PDF寬高 const imgWidth = canvas.width const imgHeight = canvas.height const pageData = canvas.toDataURL('image/jpeg', 1.0) const pdf = new jsPDF('', 'pt', [autoWidth, autoHeight]) // 當(dāng)canvas高度 未超過(guò) 一頁(yè)P(yáng)DF可顯示的canvas高度,無(wú)需分頁(yè) if (unallottedHeight <= pageHeight) { pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) pdf.save('下載多頁(yè)P(yáng)DF(自適應(yīng)紙).pdf') return } while (unallottedHeight > 0) { pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) unallottedHeight -= pageHeight position -= autoHeight if (unallottedHeight > 0) { pdf.addPage() } } pdf.save('html2canvas+jsPDF下載PDF.pdf') }) }
多頁(yè)下載(A4紙)
由于 jsPDF 單頁(yè)最大高度的限制 又或是 需求層面,我們需要實(shí)現(xiàn)自動(dòng)分頁(yè)下載
我們?cè)O(shè)置一頁(yè)P(yáng)DF頁(yè)面的寬高為A4紙尺寸,即寬 595.28pt,高 841.89pt
分頁(yè)思路:每個(gè)PDF頁(yè)面都顯示一張 canvas 圖,只不過(guò)是計(jì)算偏移量,每個(gè)PDF頁(yè)面顯示的是 canvas 的不同位置
問(wèn)題來(lái)了,如何創(chuàng)建一個(gè)新的PDF頁(yè)面呢?可以使用 jsPDF 的pdf.addPage()
const downLoadPdfA4Multiple = () => { const ele = document.body html2canvas(ele, { scale: 2, // 使用設(shè)備的像素比 }).then(canvas => { let position = 0 //頁(yè)面偏移 const A4Width = 595.28 // A4紙寬度 const A4Height = 841.89 // A4紙寬 // 一頁(yè)P(yáng)DF可顯示的canvas高度 const pageHeight = (canvas.width * A4Height) / A4Width // 未分配到PDF的canvas高度 let unallottedHeight = canvas.height // canvas對(duì)應(yīng)的PDF寬高 const imgWidth = A4Width const imgHeight = (A4Width * canvas.height) / canvas.width const pageData = canvas.toDataURL('image/jpeg', 1.0) const pdf = new jsPDF('', 'pt', [A4Width, A4Height]) // 當(dāng)canvas高度 未超過(guò) 一頁(yè)P(yáng)DF可顯示的canvas高度,無(wú)需分頁(yè) if (unallottedHeight <= pageHeight) { pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) pdf.save('下載多頁(yè)P(yáng)DF(A4紙).pdf') return } while (unallottedHeight > 0) { pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) unallottedHeight -= pageHeight position -= A4Height if (unallottedHeight > 0) { pdf.addPage() } } pdf.save('下載多頁(yè)P(yáng)DF(A4紙).pdf') }) }
源碼
GitHub - burc-li/vue-pdf: HTML 轉(zhuǎn) PDF下載(html2canvas 和 jsPDF實(shí)現(xiàn))
到此這篇關(guān)于前端實(shí)現(xiàn)HTML網(wǎng)頁(yè)轉(zhuǎn)PDF并導(dǎo)出的文章就介紹到這了,更多相關(guān)HTML網(wǎng)頁(yè)轉(zhuǎn)PDF內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
移動(dòng)設(shè)備手勢(shì)事件庫(kù)Touch.js使用詳解
這篇文章主要介紹了移動(dòng)設(shè)備手勢(shì)事件庫(kù)Touch.js的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08借用Google的Javascript API Loader來(lái)加速你的網(wǎng)站
加速頁(yè)面加載速度有一個(gè)方法就是把CSS和JS文件放到另外一個(gè)單獨(dú)的服務(wù)器上,這樣在訪問(wèn)量比較大的情況下可以分擔(dān)主服務(wù)器的壓力2009-01-01