在前端开发中,导出网页内容为 PDF 文件是一个常见需求,无论是生成报表、保存网页截图,还是打印功能。本文将介绍如何使用 html2Canvas 和 jsPDF 库实现这一功能,并提供详细的代码示例和优化建议。
一、安装插件
首先,我们需要安装 html2Canvas 和 jsPDF 两个库:
npm install html2canvas jspdf
二、依赖引入
import html2Canvas from "html2canvas";
import JsPDF from "jspdf";
三、功能实现
2.1. 步骤
- 使用 html2Canvas 将 DOM 元素转换为 Canvas 对象。
- 计算内容的宽高和 PDF 页面尺寸,确定分页逻辑。
- 使用 jsPDF 将 Canvas 转换为 PDF,并处理分页。
2.2. html部分
<div ref="contentToExport">
<!-- 你的打印内容 -->
</div>
2.3. 导出PDF
handleExportPdf() {
const dom = this.$refs.contentToExport;
html2Canvas(dom, {
useCORS: true, //解决网络图片跨域问题
width: dom.width,
height: dom.height,
windowWidth: dom.scrollWidth,
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
scale: 4, // 按比例增加分辨率
backgroundColor: "#f1f3f6", // 背景
}).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的边距,显示区域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); // 可能内容不足一页
// 用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",
20,
20,
a4w,
Math.min(a4h, (a4w * page.height) / page.width)
); // 添加图像到页面,保留10mm边距
renderedHeight += imgHeight;
if (renderedHeight < canvas.height) {
pdf.addPage(); // 如果后面还有内容,添加一个空页
}
// 预览pdf(这里我用的是事件总线把canvas传递过去展示,达到模拟pdf预览的效果,有用但效果不是很好,有需要的可以自行修改)
//this.$EventBus.$emit('open-pdf', canvas);
}
// 保存文件
pdf.save(`${this.tableTitle}.pdf`);
});
},
2.4. 导出png
handleExportImg() {
const dom = this.$refs.contentToExport;
html2Canvas(dom, {
useCORS: true, //解决网络图片跨域问题
width: dom.width,
height: dom.height,
windowWidth: dom.scrollWidth,
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
scale: 4, // 按比例增加分辨率
backgroundColor: "#f1f3f6", // 背景
}).then((canvas) => {
const imageData = canvas.toDataURL("image/png");
const a = document.createElement("a");
a.href = imageData;
a.download = `${this.tableTitle}.png`;
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
},