vue前端實(shí)現(xiàn)導(dǎo)出頁(yè)面為pdf(分頁(yè)導(dǎo)出、不分頁(yè)導(dǎo)出及分模塊導(dǎo)出)
第一步:下載插件
npm install --save html2canvas // 頁(yè)面轉(zhuǎn)圖片 npm install jspdf --save // 圖片轉(zhuǎn)pdf
第二步:main.js 文件引入
import htmlToPdf from './utils/htmlToPdf'; Vue.use(htmlToPdf);
第三步:utils/htmlToPdf.js 文件中定義方法(有三種方法:分頁(yè)導(dǎo)出、不分頁(yè)導(dǎo)出、分模塊導(dǎo)出;具體方法 見(jiàn)最下邊)

第四步:vue頁(yè)面調(diào)用方法 (htmlToPdf)

方法一: 標(biāo)準(zhǔn)打?。ǚ猪?yè)打?。蝗秉c(diǎn):分頁(yè)處會(huì)把內(nèi)容給截?cái)?/h3>
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ò)圖片跨域問(wèn)題
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顯示比例換算一頁(yè)圖像的像素高度
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)容不足一頁(yè)
// 用getImageData剪裁指定區(qū)域,并畫到前面創(chuàng)建的canvas對(duì)象中
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)); // 添加圖像到頁(yè)面,保留10mm邊距
renderedHeight += imgHeight;
if (renderedHeight < canvas.height) {
pdf.addPage();// 如果后面還有內(nèi)容,添加一個(gè)空頁(yè)
}
// 預(yù)覽pdf(這里我用的是事件總線把canvas傳遞過(guò)去展示,達(dá)到模擬pdf預(yù)覽的效果,有用但效果不是很好,有需要的可以自行修改)
//this.$EventBus.$emit('open-pdf', canvas);
}
// 保存文件
pdf.save(`${title}.pdf`);
});
};
},
}
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ò)圖片跨域問(wèn)題
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顯示比例換算一頁(yè)圖像的像素高度
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)容不足一頁(yè)
// 用getImageData剪裁指定區(qū)域,并畫到前面創(chuàng)建的canvas對(duì)象中
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)); // 添加圖像到頁(yè)面,保留10mm邊距
renderedHeight += imgHeight;
if (renderedHeight < canvas.height) {
pdf.addPage();// 如果后面還有內(nèi)容,添加一個(gè)空頁(yè)
}
// 預(yù)覽pdf(這里我用的是事件總線把canvas傳遞過(guò)去展示,達(dá)到模擬pdf預(yù)覽的效果,有用但效果不是很好,有需要的可以自行修改)
//this.$EventBus.$emit('open-pdf', canvas);
}
// 保存文件
pdf.save(`${title}.pdf`);
});
};
},
}
方法二: 標(biāo)準(zhǔn)打印(不分頁(yè)打?。?/h3>
export default {
install(Vue) {
Vue.prototype.htmlToPdf = function (name, title) {
html2Canvas(document.querySelector('#' + name), {
// allowTaint: true,
useCORS: true,
scale: 2, // 提升畫面質(zhì)量,但是會(huì)增加文件大小
dpi: window.devicePixelRatio * 1,
}).then((canvas) => {
const contentWidth = canvas.width
const contentHeight = canvas.height
/* 導(dǎo)出不分頁(yè)處理 */
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ì)量,但是會(huì)增加文件大小
dpi: window.devicePixelRatio * 1,
}).then((canvas) => {
const contentWidth = canvas.width
const contentHeight = canvas.height
/* 導(dǎo)出不分頁(yè)處理 */
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')
})
};
},
}
方法三: 分模塊打?。ㄒ粋€(gè)模塊一個(gè)頁(yè)面)
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)前可視窗口的寬度(不包含滾動(dòng)條)
const win_out = window.innerWidth // 獲得當(dāng)前窗口的寬度(包含滾動(dòng)條)
if (win_out > win_in) {
// abs = (win_o - win_i)/2; // 獲得滾動(dòng)條長(zhǎng)度的一半
abs = (win_out - win_in) / 2 // 獲得滾動(dòng)條寬度的一半
// 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)橫向沒(méi)有滾動(dòng)條的情況,因?yàn)閛ffset.left(),有無(wú)滾動(dòng)條的時(shí)候存在差值,因此
// translate的時(shí)候,要把這個(gè)差值去掉
var pdf = new JsPDF('', 'pt', 'a4')
const childrenBox = ele.children
for (let i = 0; i < childrenBox.length; i++) { // 循環(huán)傳過(guò)來(lái)的Dom的字節(jié)點(diǎn) 每個(gè)子節(jié)點(diǎn)打印成一頁(yè)pdf A4紙那么大
console.log(childrenBox,'childrenBox');
console.log(1111);
const res = await html2Canvas(childrenBox[i], {
dpi: 300,
// allowTaint: true, //允許 canvas 污染, allowTaint參數(shù)要去掉,否則是無(wú)法通過(guò)toDataURL導(dǎo)出canvas數(shù)據(jù)的
useCORS: true, // 允許canvas畫布內(nèi) 可以跨域請(qǐng)求外部鏈接圖片, 允許跨域請(qǐng)求。
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() // 避免最后多一個(gè)空白頁(yè)
}
}
pdf.save(`${title}.pdf`);
};
},
}總結(jié)
到此這篇關(guān)于vue前端實(shí)現(xiàn)導(dǎo)出頁(yè)面為pdf的文章就介紹到這了,更多相關(guān)vue前端導(dǎo)出頁(yè)面pdf內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中$nexttick,$set,$forceupdate的區(qū)別
本文主要介紹了vue中$nexttick,$set,$forceupdate的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Vue實(shí)現(xiàn)圓環(huán)進(jìn)度條的示例
這篇文章主要介紹了Vue實(shí)現(xiàn)圓環(huán)進(jìn)度條的示例,幫助大家更好的理解和使用前端框架進(jìn)行開(kāi)發(fā),感興趣的朋友可以了解下2021-02-02
element--Diaolog彈窗打開(kāi)之后渲染組件方式
這篇文章主要介紹了element--Diaolog彈窗打開(kāi)之后渲染組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
babel7.x和webpack4.x配置vue項(xiàng)目的方法步驟
這篇文章主要介紹了babel7.x和webpack4.x配置vue項(xiàng)目的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
vue中關(guān)于element的el-image 圖片預(yù)覽功能增加一個(gè)下載按鈕(操作方法)
這篇文章主要介紹了vue中關(guān)于element的el-image 圖片預(yù)覽功能增加一個(gè)下載按鈕,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
詳解element-ui設(shè)置下拉選擇切換必填和非必填
這篇文章主要介紹了詳解element-ui設(shè)置下拉選擇切換必填和非必填,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
解決vite+vue3項(xiàng)目打包后圖片不顯示或者請(qǐng)求路徑多了一個(gè)undefined問(wèn)題
這篇文章主要介紹了解決vite+vue3項(xiàng)目打包后圖片不顯示或者請(qǐng)求路徑多了一個(gè)undefined問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
基于vue3+threejs實(shí)現(xiàn)可視化大屏效果
本文主要主要講述對(duì)threejs的一些api進(jìn)行基本的封裝,在vue3項(xiàng)目中來(lái)實(shí)現(xiàn)一個(gè)可視化的3d項(xiàng)目,包含了一些常用的功能,場(chǎng)景、燈光、攝像機(jī)初始化,模型、天空盒的加載,以及鼠標(biāo)點(diǎn)擊和懸浮的事件交互,感興趣的朋友可以參考下2023-06-06

