这篇文章主要是记录了前端生成pdf文件并下载功能的实现,这个功能的实现用到了html2canvas和jsPDF。
一、实现思路:
1、使用html2canvas将指定容器内的html转为canvas,
2、将canvas转成base64的图片数据
3、使用jsPDF将图片数据插入到pdf页面中
二、实现过程
1、安装
npm install html2canvas
npm install jspdf
2、封装一个公用方法:useCompToPDF.ts
注:这个方法的具体实现是取自网友们分享的方法,来源~
import html2canvas from 'html2canvas';
import jsPDF from "jspdf";
interface CompToPDFProps {
fileName: string;
}
const PDFFile = {
A4:[592.28, 841.89]
}
const useCompToPDF = (props: CompToPDFProps) => {
const { fileName } = props
const exportPDF = (element: HTMLElement | null) => {
if (element) {
html2canvas(element, {
backgroundColor: null,
allowTaint: true,
useCORS: true,
scale: 2,
}).then((canvas) => {
// 获取画布的宽高
let canvasWidth = canvas.width
let canvasHeight = canvas.height
// 一页pdf显示HTML生成的canvas高度
let pdfPageHeight = (PDFFile.A4[1] / PDFFile.A4[0]) * canvasWidth
// 未生成pdf的html页面内的高度
let pdfAllHeight = canvasHeight
// 页面偏移
let position = 0
let pageData = canvas.toDataURL('image/jpeg', 1.0)
let imgWidth = PDFFile.A4[0] - 60
let imgHeight = (canvasHeight / canvasWidth) * PDFFile.A4[0]
let pdf = new jsPDF('p', 'pt', PDFFile.A4)
if (pdfAllHeight < pdfPageHeight) {
pdf.addImage(pageData, 'JPEG', 30 ,0, imgWidth, imgHeight)
} else {
while (pdfAllHeight > 0) {
pdf.addImage(pageData, 'JPEG', 30, position, imgWidth, imgHeight)
pdfAllHeight -= pdfPageHeight
position -= PDFFile.A4[1]
if (pdfAllHeight > 0) {
pdf.addPage()
}
}
}
pdf.save(`${fileName}.pdf`)
})
}
}
return {
exportPDF
}
}
export default useCompToPDF
3、使用
import useCompToPDF from './useCompToPDF';
export default function Page() {
const { exportPDF } = useCompToPDF({fileName:'haha.pdf'})
return (
<Fragment>
<button onClick={() => {
let target = document.getElementById('pdfBox');
exportPDF(target)
}>下载</button>
<div
style={{
backgroundColor: '#ffffff',
position: 'absolute',
left: -1000,
}}
id="pdfBox"
></div>
</Fragment>
);
}
}
三、遇到的问题
在实现的过程中,我遇到了以下两个问题:
1、canvas中一片空白,没有预期的网页内容
原因:目标容器的高度设置为0了,或者设置display:none等方式使目标内容在页面上不可见,这会导致转为canvas时内容空白的问题。
解决方式:如果目标元素并不需要展示在页面上,那么可以使用绝对定位的方式,让它“消失”。
2、html2canvas返回的canvas 的背景是黑色的。虽然已经按照官方文档设置了backgroundColor属性,但仍然没起作用。
解决方式:无意间增加设置了scale属性,背景色就正常了。如果你也遇到了同样的问题,那这也不妨是一个解决的方式。不过虽然问题解决了,但是不是很明白为什么设置了scale就正常了,有了解的小伙伴欢迎帮我解惑吖~
四、遗留问题
还有一个问题,就是如果生成的图片很长,一页放不下,那图片会被截断显示在不同页上,截断的位置就有可能会把某行文字截断,这个问题目前还没有找到合适的解决方案。 不知道你有没有合适的解决方案呢,希望能够分享给我吖~
ok, 本篇就先记录这么多。