目录
1、安装依赖
导出PDF通常涉及将HTML内容转换为图片(截图),然后将这些图片插入到PDF文档中。这个过程可以通过使用
html2canvas
和jspdf
这两个库来实现:npm install jspdf html2canvas
或 cnpm
install jspdf html2canvas安装完成后,package.json文件生成如下:
2、demo
2.1 demo1导出效果
源码中 【导出PDF】导出时,不会分页导出。
2.2 demo2导出效果
源码中 【导出PDF2】导出时,会分页导出。
2.3 demo3导出效果
源码中 【导出PDF3】导出时,会分页导出。
3、源码
<template>
<div>
<div style="margin-top: 50px;text-align: center" >
<el-button type="primary" @click="exportPDF">导出PDF</el-button>
<el-button type="primary" @click="exportPDF2">导出PDF2</el-button>
<el-button type="primary" @click="getPdf()" >导出PDF3</el-button>
</div>
<div style="margin-left: 200px;margin-top: 10px;margin-right: 150px" ref="pdfContent" id="pdfDom" class="mmm" >
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="name" label="姓名" width="180"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
</el-table>
<h1>1Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>2Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>3Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
<h1>4Element 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。</h1>
</div>
</div>
</template>
<script>
import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
export default {
data() {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}],
htmlTitle:"PDF测试"
}
},
methods: {
async exportPDF() {
const content = this.$refs.pdfContent;
const canvas = await html2canvas(content);
const imgData = canvas.toDataURL('image/png');
const doc = new jsPDF({
orientation: 'portrait',
unit: 'px',
format: 'a4',
});
const imgProps= doc.getImageProperties(imgData);
const pdfWidth = doc.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
doc.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
doc.save('导出pdf测试1.pdf');
},
exportPDF2() {
html2canvas(document.querySelector('#pdfDom'), {
allowTaint: false, // 是否允许跨域图像。会污染画布,导致无法使用canvas.toDataURL 方法
backgroundColor: '#fff', // 画布背景色(如果未在DOM中指定)。设置null为透明
useCORS: true, // 是否尝试使用CORS从服务器加载图像
dpi: 500, // 导出pdf清晰度
scale: window.devicePixelRatio, // 用于渲染的比例。默认为浏览器设备像素比率。
}
).then(function (canvas) {
var imageData = canvas.toDataURL('image/jpeg', 1.0); // html生成图片的数据
const canvasWidth = canvas.width; // 原本的html页面的宽高
const canvasHeight = canvas.height;
// 当分辨率是72像素/英寸时,A4纸像素长宽分别是842×595
var a4Width = 595; // A4 宽度
var a4Height = (595 / canvasWidth) * canvasHeight; // A4总高度
let pageHeight = canvasWidth / 595 * 842; // 生成pdf的一页显示html的高度
let restHeight = canvasHeight; // 未生成pdf的html页面高度,最初是整体的高度
var position = 0; // 页面上下偏移的大小
/**
* 参数1:方向:l:横向 p:纵向
* 参数2:单位:"pt"、"mm"、"cm"、"m"、"in"、"px"
* 参数3:格式:默认为a4
*/
var pdf = new jsPDF('p', 'pt', 'a4');
if (restHeight < pageHeight) { // 当内容未超过pdf一页显示的范围,无需分页
/**
* 将图像添加到PDF中
* 参数1:图片的url
* 参数2:图片的格式
* 参数3:图片上下偏移的大小
* 参数4:原始宽度
* 参数5:原始高度
*/
pdf.addImage(imageData, 'JPEG', 0, position, a4Width, a4Height);
} else {
while (restHeight > 0) {
pdf.addImage(imageData, 'JPEG', 0, position, a4Width, a4Height)
restHeight -= pageHeight;
position -= 842;
if (restHeight > 0) {
pdf.addPage(); // 在PDF文档中添加新页面
}
}
}
pdf.save("导出pdf测试2" + '.pdf')
}
)
},
},
};
</script>
<style>
.mmm {
background: linear-gradient(to right, #39fad7, #f9faa1,#39fad7); /* 标准的语法 */
}
</style>
3.1 demo1
源码中 【导出PDF】按钮,不会分页导出,会截断数据,适用于只需要导出一页的数据,如证件、行数少的表格数据等。
3.2 demo2
源码中 【导出PDF2】按钮,会分页导出,实际应用中根据需求进行处理、设置。
3.3 demo3
源码中 【导出PDF3】按钮,会分页导出,封装了方法,本质和【导出PDF2】按钮一样。
<el-button type="primary" @click="getPdf()" >导出PDF3</el-button>
此按钮为封装方法,所以当前源码搜不到。
1)、在utils文件夹中创建htmlToPdf.js的文件,如下:
// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
install (Vue, options) {
Vue.prototype.getPdf = function () {
var title = this.htmlTitle
html2Canvas(document.querySelector('#pdfDom'), {
allowTaint: true
}).then(function (canvas) {
let contentWidth = canvas.width
let contentHeight = canvas.height
let pageHeight = contentWidth / 592.28 * 841.89
let leftHeight = contentHeight
let position = 0
let imgWidth = 595.28
let imgHeight = 592.28 / contentWidth * contentHeight
let pageData = canvas.toDataURL('image/jpeg', 1.0)
let PDF = new JsPDF('p', '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()
}
}
}
PDF.save(title + '.pdf')
}
)
}
}
}
2)、在main.js中注册自定义的插件htmlToPdf.js
3)、方法、属性解释及导出文件
getPdf()是我们在main.js中绑定在Vue中的,直接调用即可,无需在methods中写方法; htmlTitle:"PDF测试" //主页面中定义文件名称,htmlToPdf.js中获取。