vue前端實現(xiàn)導(dǎo)出頁面為pdf(分頁導(dǎo)出、不分頁導(dǎo)出及分模塊導(dǎo)出)
更新時間:2024年06月12日 08:30:48 作者:鹽多碧咸。。
在實際應(yīng)用中可能用戶希望將系統(tǒng)中一個頁面展示的所有數(shù)據(jù)報表,用PDF的文件格式下載下來,以便于其他用途,這篇文章主要給大家介紹了關(guān)于vue前端實現(xiàn)導(dǎo)出頁面為pdf(分頁導(dǎo)出、不分頁導(dǎo)出及分模塊導(dǎo)出)的相關(guān)資料,需要的朋友可以參考下
第一步:下載插件
npm install --save html2canvas // 頁面轉(zhuǎn)圖片 npm install jspdf --save // 圖片轉(zhuǎn)pdf
第二步:main.js 文件引入
import htmlToPdf from './utils/htmlToPdf'; Vue.use(htmlToPdf);
第三步:utils/htmlToPdf.js 文件中定義方法(有三種方法:分頁導(dǎo)出、不分頁導(dǎo)出、分模塊導(dǎo)出;具體方法 見最下邊)
第四步:vue頁面調(diào)用方法 (htmlToPdf)
方法一: 標(biāo)準(zhǔn)打?。ǚ猪摯蛴。?;缺點:分頁處會把內(nèi)容給截斷
export default { install(Vue) { // eslint-disable-next-line func-names Vue.prototype.htmlToPdf = function (ele, title) { const dom = document.querySelector('#' + ele) html2Canvas(dom, { useCORS: true,//解決網(wǎng)絡(luò)圖片跨域問題 width: dom.width, height: dom.height, windowWidth: dom.scrollWidth, dpi: window.devicePixelRatio * 4, // 將分辨率提高到特定的DPI 提高四倍 scale: 4, // 按比例增加分辨率 }).then((canvas) => { // eslint-disable-next-line new-cap const pdf = new JsPDF('p', 'mm', 'a4'); // A4紙,縱向 const ctx = canvas.getContext('2d'); const a4w = 170; const a4h = 250; // A4大小,210mm x 297mm,四邊各保留20mm的邊距,顯示區(qū)域170x257 const imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4顯示比例換算一頁圖像的像素高度 let renderedHeight = 0; while (renderedHeight < canvas.height) { const page = document.createElement('canvas'); page.width = canvas.width; page.height = Math.min(imgHeight, canvas.height - renderedHeight);// 可能內(nèi)容不足一頁 // 用getImageData剪裁指定區(qū)域,并畫到前面創(chuàng)建的canvas對象中 page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0); pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 20, 20, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加圖像到頁面,保留10mm邊距 renderedHeight += imgHeight; if (renderedHeight < canvas.height) { pdf.addPage();// 如果后面還有內(nèi)容,添加一個空頁 } // 預(yù)覽pdf(這里我用的是事件總線把canvas傳遞過去展示,達到模擬pdf預(yù)覽的效果,有用但效果不是很好,有需要的可以自行修改) //this.$EventBus.$emit('open-pdf', canvas); } // 保存文件 pdf.save(`${title}.pdf`); }); }; }, }
方法二: 標(biāo)準(zhǔn)打?。ú环猪摯蛴。?/h3>
export default {
install(Vue) {
Vue.prototype.htmlToPdf = function (name, title) {
html2Canvas(document.querySelector('#' + name), {
// allowTaint: true,
useCORS: true,
scale: 2, // 提升畫面質(zhì)量,但是會增加文件大小
dpi: window.devicePixelRatio * 1,
}).then((canvas) => {
const contentWidth = canvas.width
const contentHeight = canvas.height
/* 導(dǎo)出不分頁處理 */
const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pdfWidth = (contentWidth + 10) / 2 * 0.75
const pdfHeight = (contentHeight + 200) / 2 * 0.75 // 500為底部留白
const imgWidth = pdfWidth
const imgHeight = (contentHeight / 2 * 0.75) // 內(nèi)容圖片這里不需要留白的距離
const PDF = new JsPDF('', 'pt', [ pdfWidth + 50, pdfHeight + 100, ])
PDF.addImage(pageData, 'jpeg', 33, 33, imgWidth, imgHeight)
PDF.save(title + '.pdf')
})
};
},
}
export default { install(Vue) { Vue.prototype.htmlToPdf = function (name, title) { html2Canvas(document.querySelector('#' + name), { // allowTaint: true, useCORS: true, scale: 2, // 提升畫面質(zhì)量,但是會增加文件大小 dpi: window.devicePixelRatio * 1, }).then((canvas) => { const contentWidth = canvas.width const contentHeight = canvas.height /* 導(dǎo)出不分頁處理 */ const pageData = canvas.toDataURL('image/jpeg', 1.0) const pdfWidth = (contentWidth + 10) / 2 * 0.75 const pdfHeight = (contentHeight + 200) / 2 * 0.75 // 500為底部留白 const imgWidth = pdfWidth const imgHeight = (contentHeight / 2 * 0.75) // 內(nèi)容圖片這里不需要留白的距離 const PDF = new JsPDF('', 'pt', [ pdfWidth + 50, pdfHeight + 100, ]) PDF.addImage(pageData, 'jpeg', 33, 33, imgWidth, imgHeight) PDF.save(title + '.pdf') }) }; }, }
方法三: 分模塊打?。ㄒ粋€模塊一個頁面)
export default { install(Vue) { Vue.prototype.htmlToPdf = async function (name, title) { const ele = document.querySelector('#' + name) const eleW = ele.offsetWidth// 獲得該容器的寬 const eleH = ele.offsetHeight// 獲得該容器的高 const eleOffsetTop = ele.offsetTop // 獲得該容器到文檔頂部的距離 const eleOffsetLeft = ele.offsetLeft // 獲得該容器到文檔最左的距離 var canvas = document.createElement('canvas') var abs = 0 const win_in = document.documentElement.clientWidth || document.body.clientWidth // 獲得當(dāng)前可視窗口的寬度(不包含滾動條) const win_out = window.innerWidth // 獲得當(dāng)前窗口的寬度(包含滾動條) if (win_out > win_in) { // abs = (win_o - win_i)/2; // 獲得滾動條長度的一半 abs = (win_out - win_in) / 2 // 獲得滾動條寬度的一半 // console.log(a, '新abs'); } canvas.width = eleW * 2 // 將畫布寬&&高放大兩倍 canvas.height = eleH * 2 var context = canvas.getContext('2d') context.scale(2, 2) context.translate(-eleOffsetLeft - abs, -eleOffsetTop) // 這里默認(rèn)橫向沒有滾動條的情況,因為offset.left(),有無滾動條的時候存在差值,因此 // translate的時候,要把這個差值去掉 var pdf = new JsPDF('', 'pt', 'a4') const childrenBox = ele.children for (let i = 0; i < childrenBox.length; i++) { // 循環(huán)傳過來的Dom的字節(jié)點 每個子節(jié)點打印成一頁pdf A4紙那么大 console.log(childrenBox,'childrenBox'); console.log(1111); const res = await html2Canvas(childrenBox[i], { dpi: 300, // allowTaint: true, //允許 canvas 污染, allowTaint參數(shù)要去掉,否則是無法通過toDataURL導(dǎo)出canvas數(shù)據(jù)的 useCORS: true, // 允許canvas畫布內(nèi) 可以跨域請求外部鏈接圖片, 允許跨域請求。 scale: 4, // 提升導(dǎo)出的文件的分辨率 }) var pageData = res.toDataURL('image/jpeg', 1.0) var contentWidth = res.width var contentHeight = res.height var imgWidth = 555.28 var imgHeight = 552.28 / contentWidth * contentHeight pdf.addImage(pageData, 'JPEG', 20, 20, imgWidth, imgHeight) if (i < childrenBox.length - 1) { pdf.addPage() // 避免最后多一個空白頁 } } pdf.save(`${title}.pdf`); }; }, }
總結(jié)
到此這篇關(guān)于vue前端實現(xiàn)導(dǎo)出頁面為pdf的文章就介紹到這了,更多相關(guān)vue前端導(dǎo)出頁面pdf內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項目中的遇錯:Invalid?Host?header問題
這篇文章主要介紹了vue項目中的遇錯:Invalid?Host?header問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07element-plus的自動導(dǎo)入和按需導(dǎo)入方式詳解
之前使用 ElementPlus 做項目的時候,由于不會使用按需引入耽誤了不少時間,這篇文章主要給大家介紹了關(guān)于element-plus自動導(dǎo)入和按需導(dǎo)入的相關(guān)資料,需要的朋友可以參考下2022-08-08vite+vue3中使用mock模擬數(shù)據(jù)問題
這篇文章主要介紹了vite+vue3中使用mock模擬數(shù)據(jù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03