html2canvas + jspdf
1. 首先安装这两个依赖
npm install html2canvas jspdf
2. 建议新建htmlToPdf.js文件
import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'
function downloadPDF(ele, pdfName) {
let eleW = ele.offsetWidth
let eleH = ele.offsetHeight
let eleOffsetTop = ele.offsetTop
let eleOffsetLeft = ele.offsetLeft
var canvas = document.createElement('canvas')
var abs = 0
let win_in = document.documentElement.clientWidth || document.body.clientWidth
let win_out = window.innerWidth
if (win_out > win_in) {
abs = (win_out - win_in) / 2
}
canvas.width = eleW * 2
canvas.height = eleH * 2
var context = canvas.getContext('2d')
context.scale(2, 2)
context.translate(-eleOffsetLeft - abs, -eleOffsetTop)
let pageHeightNum = (canvas.width / 2 / 592.28) * 841.89
let lableListID = document.getElementsByClassName('target-node-item')
for (let i = 0; i < lableListID.length; i++) {
let multiple = Math.ceil(
(lableListID[i].offsetTop + lableListID[i].offsetHeight) / pageHeightNum
)
if (isSplit(lableListID, i, multiple * pageHeightNum)) {
let divParent = lableListID[i].parentNode
let newNode = document.createElement('div')
newNode.className = 'seatDiv'
newNode.style.background = '#ffffff'
let _H =
multiple * pageHeightNum -
(lableListID[i].offsetTop + lableListID[i].offsetHeight)
newNode.style.height = _H + 50 + 'px'
let next = lableListID[i].nextSibling
if (next) {
divParent.insertBefore(newNode, next)
} else {
divParent.appendChild(newNode)
}
}
}
html2canvas(ele, {
dpi: 300,
useCORS: true
}).then((canvas) => {
var contentWidth = canvas.width
var contentHeight = canvas.height
var pageHeight = (contentWidth / 592.28) * 841.89
var leftHeight = contentHeight
var position = 0
var imgWidth = 595.28
var imgHeight = (595.28 / contentWidth) * contentHeight
var pageData = canvas.toDataURL('image/jpeg', 1.0)
var 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()
}
}
}
let delArr = document.getElementsByClassName('seatDiv')
for (let i = delArr.length - 1; i >= 0; i--) {
if (delArr[i] && delArr[i].parentElement) {
delArr[i].remove()
}
}
pdf.save(pdfName)
})
}
function isSplit(nodes, index, pageHeight) {
if (
nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight &&
nodes[index + 1] &&
nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight
) {
return true
}
return false
}
export default {
downloadPDF
}
3.组件中使用
<template>
<div id="app">
<button @click="handleExport">导出</button>
<table id="pdfBox">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr v-for="item in obj" :key="item.age">
<td>{{ item.name }}</td>
<td>{{ item.date }}</td>
<td>{{ item.address }}</td>
</tr>
</tbody>
</table>
<button type="button" style="margin-top: 20px" @click="btnClick">
导出PDF
</button>
</div>
</template>
<script>
import htmlToPdf from '@/utils/htmlToPdf'
export default {
name: 'App',
components: {},
data() {
return {
obj: [
{ name: 'John Doe', date: 28, address: 'New York' },
{ name: 'Jane Smith', date: 35, address: 'London' },
{ name: 'David Johnson', date: 42, address: 'Paris' },
{
date: '2016-05-08',
name: '王小虎',
address: '武汉市洪山区文化大道'
},
{
date: '2016-05-06',
name: '王小虎',
address: '武汉市洪山区文化大道'
},
{
date: '2016-05-07',
name: '王小虎',
address: '武汉市洪山区文化大道'
},
{
date: '2016-05-06',
name: '王小虎',
address: '南京市江宁区将军大道'
},
{
date: '2016-05-07',
name: '王小虎',
address: '武汉市洪山区文化大道'
}
],
exportPDFtitle: '页面导出PDF文件名a'
}
},
methods: {
btnClick() {
htmlToPdf.downloadPDF(document.getElementById('pdfBox'), '下载pdf文件名')
}
}
}
</script>