项目场景:
提示:这里简述项目相关背景:
在项目中会有一些需要页面转成PDF的情况,这里需要配合一些插件可以完成
使用html2canvas将使用canvas将页面转为base64图片流,并插入jspdf插件中,保存并下载pdf。
安装依赖
提示:这里描述项目中遇到的问题:
npm i html2canvas
npm i jspdf
解决方案1:
提示:这里填写该问题的具体解决方案:
1:创建htmlToPdf.ts文件
// 页面导出为pdf格式
import html2Canvas from 'html2canvas';
import jsPDF from 'jspdf';
const htmlToPdf = {
getPdf(title) {
html2Canvas(document.querySelector('#pdfStyle'), {
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
dpi: window.devicePixelRatio * 4, //将分辨率提高到特定的DPI 提高四倍
scale: 2, //按比例增加分辨率
}).then((canvas) => {
const pdf = new jsPDF('p', 'mm', 'a4'); //A4纸,纵向
const ctx = canvas.getContext('2d')
const a4w = 190
const a4h = 272 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
//按A4显示比例换算一页图像的像素高度
const imgHeight = Math.floor((a4h * canvas.width) / a4w)
let renderedHeight = 0;
while (renderedHeight < canvas.height) {
const page = document.createElement('canvas');
page.width = canvas.width;
//可能内容不足一页
page.height = Math.min(imgHeight, canvas.height - renderedHeight);
//用getImageData剪裁指定区域,并画到前面创建的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',
10,
10,
a4w,
Math.min(a4h, (a4w * page.height) / page.width),
); //添加图像到页面,保留10mm边距
renderedHeight += imgHeight;
if (renderedHeight < canvas.height) {
pdf.addPage(); //如果后面还有内容,添加一个空页
}
// delete page;
}
//保存文件
pdf.save(title + '.pdf');
// loading = false;
// console.log(loading);
});
},
};
export default htmlToPdf;
2:在页面中使用
...
<!-- 按钮 -->
<el-button size="mini" type="primary" @click="pdfFunc" :loading="loading">
转成pdf
</el-button>
...
<div id="pdfDom">
<!-- 此处是希望转成pdf的部分的内容,用一个大div盒子包起来 -->
</div>
<script setup>
// 导入htmlToPdf.js
import htmlToPdf from '@/utils/htmlToPdf';
const pdfFunc = () => {
loading.value = true;
// 调用htmlToPdf工具函数
htmlToPdf.getPdf('文档名称');
// 定时器模拟按钮loading动画的时间
setTimeout(() => {
loading.value = false;
ElMessage.success('打印成功!');
}, 1000);
}
</script>
解决方案2:
1:创建htmlToPdf.ts文件
// utils/htmlToPdf.js:导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
install(Vue, options) {
// id-导出pdf的div容器;title-导出文件标题
Vue.prototype.htmlToPdf = (id, title) => {
const element = document.getElementById(`${id}`)
const opts = {
scale: 4, // 缩放比例,提高生成图片清晰度
useCORS: true, // 允许加载跨域的图片
allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
tainttest: true, // 检测每张图片已经加载完成
logging: true // 日志开关,发布的时候记得改成 false
}
html2Canvas(element, opts)
.then((canvas) => {
console.log(canvas)
const contentWidth = canvas.width
const contentHeight = canvas.height
// 一页pdf显示html页面生成的canvas高度;
const pageHeight = (contentWidth / 592.28) * 841.89
// 未生成pdf的html页面高度
let leftHeight = contentHeight
// 页面偏移
let position = 0
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
const imgWidth = 595.28
const imgHeight = (592.28 / contentWidth) * contentHeight
const pageData = canvas.toDataURL('image/jpeg', 1.0)
console.log(pageData)
// a4纸纵向,一般默认使用;new JsPDF('landscape'); 横向页面
const PDF = new JsPDF('', 'pt', 'a4')
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
// addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
} else {
// 超过一页时,分页打印(每页高度841.89)
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
if (leftHeight > 0) {
PDF.addPage()
}
}
}
PDF.save(title + '.pdf')
})
.catch((error) => {
console.log('打印失败', error)
})
}
}
}
2:在页面中使用
<template>
<div>
<div
id="pdfDom"
>
测试数据
</div>
<el-button
type="primary" round
style="background: #4849FF"
@click="btnClick">导出PDF</el-button>
</div>
</template>
<script>
import JsPDF from 'jspdf'
import html2Canvas from 'html2canvas'
mounted() {
// 导出pdf
btnClick() {
this.$nextTick(() => {
this.htmlToPdf('pdfDom', '个人报告')
})
},
},
</script>