vue3+ElementUI html導出Pdf方式
更新時間:2026年03月10日 09:17:52 作者:風隨心飛飛
文章介紹了如何使用html2canvas和jspdf兩個依賴生成PDF文件,并在Vue項目中應用,通過將PDF轉(zhuǎn)換為base64Url,可以方便地進行上傳和下載操作
1. 安裝依賴
主要用到以下兩個依賴:
html2canvas:通過獲取HTML的某個元素,然后生成Canvas,能讓用戶保存為圖片。jspdf:基于HTML5的客戶端解決方案,用于生成各種用途的 PDF 文檔。
npm i html2canvas jspdf --save
package.json
"dependencies": {
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"vue": "^3.2.37"
}
2. 創(chuàng)建htmlToPdf.js
/* eslint-disable */
//不使用JQuery版的
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';
/**
* @param ele 要生成 pdf 的DOM元素(容器)
* @param padfName PDF文件生成后的文件名字
* */
function js_getDPI() {
var arrDPI = new Array();
if (window.screen.deviceXDPI != undefined) {
arrDPI[0] = window.screen.deviceXDPI;
arrDPI[1] = window.screen.deviceYDPI;
}
else {
var tmpNode = document.createElement("DIV");
tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
document.body.appendChild(tmpNode);
arrDPI[0] = parseInt(tmpNode.offsetWidth);
arrDPI[1] = parseInt(tmpNode.offsetHeight);
tmpNode.parentNode.removeChild(tmpNode);
}
return arrDPI;
}
export function getPdfUrl(ele, pdfName,callback){
let eleW = ele.offsetWidth;// 獲得該容器的寬
let eleH = ele.offsetHeight;// 獲得該容器的高
let eleOffsetTop = ele.offsetTop; // 獲得該容器到文檔頂部的距離
let eleOffsetLeft = ele.offsetLeft; // 獲得該容器到文檔最左的距離
var canvas = document.createElement("canvas");
var abs = 0;
let win_in = document.documentElement.clientWidth || document.body.clientWidth; // 獲得當前可視窗口的寬度(不包含滾動條)
let win_out = window.innerWidth; // 獲得當前窗口的寬度(包含滾動條)
if(win_out>win_in){
// abs = (win_o - win_i)/2; // 獲得滾動條長度的一半
abs = (win_out - win_in)/2; // 獲得滾動條寬度的一半
}
canvas.width = eleW * 2; // 將畫布寬&&高放大兩倍
canvas.height = eleH * 2;
var context = canvas.getContext("2d");
context.scale(2, 2);
context.translate(-eleOffsetLeft -abs, -eleOffsetTop);
// 這里默認橫向沒有滾動條的情況,因為offset.left(),有無滾動條的時候存在差值,因此
// translate的時候,要把這個差值去掉
// html2canvas(element).then( (canvas)=>{ //報錯
// html2canvas(element[0]).then( (canvas)=>{
html2canvas( ele, {
// dpi: 300,
width:eleW+135,
height:eleH,
// allowTaint: true, //允許 canvas 污染, allowTaint參數(shù)要去掉,否則是無法通過toDataURL導出canvas數(shù)據(jù)的
useCORS:true //允許canvas畫布內(nèi) 可以跨域請求外部鏈接圖片, 允許跨域請求。
} ).then( (canvas)=>{
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一頁pdf顯示html頁面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html頁面高度
var leftHeight = contentHeight;
//頁面偏移
var position = 30;
//a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
var imgWidth = 595.28;
var imgHeight = 595.28/contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new JsPDF('', 'pt', 'a4');
//有兩個高度需要區(qū)分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
//當內(nèi)容未超過pdf一頁顯示的范圍,無需分頁
if (leftHeight < pageHeight) {
//在pdf.addImage(pageData, 'JPEG', 左,上,寬度,高度)設置在pdf中顯示;
pdf.addImage(pageData, 'JPEG', 30, 30, imgWidth, imgHeight);
// pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
} else { // 分頁
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 30, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白頁
if(leftHeight > 0) {
pdf.addPage();
}
}
}
//可動態(tài)生成
// pdf.save(pdfName);
var buffer = pdf.output("datauristring");
callback(buffer)
})
}
export function downloadPDF2(ele, pdfName,callback){
let eleW = ele.offsetWidth;// 獲得該容器的寬
let eleH = ele.offsetHeight;// 獲得該容器的高
let eleOffsetTop = ele.offsetTop; // 獲得該容器到文檔頂部的距離
let eleOffsetLeft = ele.offsetLeft; // 獲得該容器到文檔最左的距離
var canvas = document.createElement("canvas");
var abs = 0;
let win_in = document.documentElement.clientWidth || document.body.clientWidth; // 獲得當前可視窗口的寬度(不包含滾動條)
let win_out = window.innerWidth; // 獲得當前窗口的寬度(包含滾動條)
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);
// 這里默認橫向沒有滾動條的情況,因為offset.left(),有無滾動條的時候存在差值,因此
// translate的時候,要把這個差值去掉
// html2canvas(element).then( (canvas)=>{ //報錯
// html2canvas(element[0]).then( (canvas)=>{
html2canvas( ele, {
// dpi: 300,
width:eleW+135,
height:eleH,
// allowTaint: true, //允許 canvas 污染, allowTaint參數(shù)要去掉,否則是無法通過toDataURL導出canvas數(shù)據(jù)的
useCORS:true //允許canvas畫布內(nèi) 可以跨域請求外部鏈接圖片, 允許跨域請求。
} ).then( (canvas)=>{
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一頁pdf顯示html頁面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html頁面高度
var leftHeight = contentHeight;
//頁面偏移
var position = 30;
//a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
var imgWidth = 595.28;
var imgHeight = 595.28/contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new JsPDF('', 'pt', 'a4');
//有兩個高度需要區(qū)分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
//當內(nèi)容未超過pdf一頁顯示的范圍,無需分頁
if (leftHeight < pageHeight) {
//在pdf.addImage(pageData, 'JPEG', 左,上,寬度,高度)設置在pdf中顯示;
pdf.addImage(pageData, 'JPEG', 30, 30, imgWidth, imgHeight);
// pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
} else { // 分頁
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 30, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白頁
if(leftHeight > 0) {
pdf.addPage();
}
}
}
//可動態(tài)生成
pdf.save(pdfName + '.pdf');
callback()
})
}
3. 如何使用htmlToPdf.js
App.vue為例,這樣就得到了pdf-con范圍內(nèi)的PDF的base64Url, 可以轉(zhuǎn)成file對象去做上傳,提交給后端參數(shù)

調(diào)用此方法后瀏覽器就會直接下載PDF

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
elementUI+Springboot實現(xiàn)導出excel功能的全過程
這篇文章主要介紹了elementUI+Springboot實現(xiàn)導出excel功能,現(xiàn)在也對這個導出功能進行一個匯總整理寫出來,結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09
vue3中的數(shù)據(jù)劫持的最新實現(xiàn)方案的proxy示例詳解
Vue3中使用Proxy實現(xiàn)數(shù)據(jù)劫持,解決了Vue2中數(shù)組和對象劫持的遺留問題,Proxy可以修改某些操作的默認行為,通過get和set方法實現(xiàn)數(shù)據(jù)的劫持和保護機制,感興趣的朋友跟隨小編一起看看吧2024-11-11
Vue 父子組件的數(shù)據(jù)傳遞、修改和更新方法
下面小編就為大家分享一篇Vue 父子組件的數(shù)據(jù)傳遞、修改和更新方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03
vue項目刷新當前頁面的三種方式(重載當前頁面數(shù)據(jù))
這篇文章主要介紹了vue項目刷新當前頁面的三種方式(重載當前頁面數(shù)據(jù)),本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01

