上篇刚写了html2canvas用法:使用html2canvas将页面或某个dom元素保存/下载为图片感兴趣可以去看下。
首先jspdf这个库就是用来生成pdf的,那为什么还需要使用到html2canvas。是因为jspdf直接生成pdf的话,用法可能会有些繁琐,并且可能不能保证原来的样式,不美观,也不满足需求。
所以我们先使用html2canvas将目标dom元素转为canvas,然后调用canvas的toDataURL方法将其转为base64编码,然后再将图片添加到pdf中就可以了。
1. 安装
pnpm add html2canvas
pnpm add jspdf
2. 引入
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
3. 封装使用
我这里将生成pdf方法单独封装在generatePdf.js文件中,向外导出这个方法拱外界使用
generatePdf.js
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
/**
* 将指定的dom元素转为pdf 并下载
* @param {element} dom
* @param {string} filename
*/
export default function (dom, filename) {
document.documentElement.scrollTop = 0
document.body.scrollTop = 0
html2Canvas(dom, {
allowTaint: true,
useCORS: true,
// scale: 2,
height: dom?.scrollHeight || 1080,
windowHeight: dom?.scrollHeight || 1080
}).then(canvas => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
// 一页pdf显示html页面生成的canvas高度;
let pageHeight = contentWidth * 841.89 / 592.28;
// 未生成pdf的html页面高度
let leftHeight = contentHeight;
// 页面偏移
let position = 0;
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
let imgWidth = 595.28;
let imgHeight = 592.28 / contentWidth * contentHeight;
let pageData = canvas.toDataURL('image/jpeg', 1.0);
let pdf = new JsPDF('', 'pt', 'a4');
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
/**
* output可选参数
* arraybuffer
* blob
* bloburi
* datauristring
* datauri
* dataurlnewwindow
* pdfobjectnewwindow
* pdfjsnewwindow
*/
// // 拿到生成的pdf的文件流 Blob二进制对象
// const pdfBlob = pdf.output('blob')
// 下载操作
filename = filename.indexOf('.pdf') >= 0 ? filename : filename + '.pdf'
pdf.save(filename);
})
}
在使用的时候将要转为pdf的目标dom元素传入即可,第二个参数是当前转成pdf并下载的pdf文件名称
下面贴一下测试页面完整代码
<template>
<div class="jspdf">
<div class="toolbar">
<button @click="toPdf">转为pdf</button>
</div>
<div class="pdf-container">
<div class="chart-container">
<Echart id="echart1" />
</div>
<div class="chart-container">
<Echart id="echart2" />
</div>
<div class="chart-container">
<Echart id="echart3" />
</div>
<div class="chart-container">
<Echart id="echart4" />
</div>
</div>
</div>
</template>
<script setup>
import Echart from './echart.vue'
import generatePdf from './generatePdf'
// 生成pdf
const toPdf = () => {
generatePdf(document.querySelector('.pdf-container'), '图表')
}
</script>
<style scoped>
.jspdf {
width: 100%;
height: 100%;
padding: 20px 0 0 20px;
box-sizing: border-box;
overflow-x: hidden;
}
.pdf-container {
width: 600px;
overflow: auto;
overflow-x: hidden;
}
.chart-container {
width: 100%;
height: 500px;
border: 1px dashed red;
padding: 20px;
box-sizing: border-box;
}
.toolbar {
width: 100%;
height: 50px;
display: flex;
align-items: center;
}
button {
padding: 8px 15px;
box-sizing: border-box;
}
</style>
4. 效果: