import htmlToPdf from “@/util/htmlToPdf”
Vue.use(htmlToPdf)
import html2canvas from “html2canvas”
import JsPDF from “jspdf”
/**
@param ele要生成 pdf 的DOM元素(容器)
@param el_class 不能分割的元素
@param pdfFileName PDF文件生成后的文件名字
*/
export default {
install(Vue, options) {
Vue.prototype.getPdfFromHtml = (ele, el_class, pdfFileName) => {
//a4纸的尺寸[595.28,841.89],单位像素,html页面生成的canvas在pdf中图片的宽高
//ele 要导出的容器 el_class标记不能分割的元素 pdfFileName导出的文件名
let A4_WIDTH = 595.28
let A4_HEIGHT = 841.89
function splitPage(dom) {
const pageOffsetTop = dom.offsetTop
const pageOffsetWidth = dom.offsetWidth
const pageOffsetHeight = dom.offsetHeight
const $unitElements = dom.querySelectorAll('.' + el_class) //标记不能分割的元素
const peerPageHeight = pageOffsetWidth / A4_WIDTH * A4_HEIGHT // 获取缩放后的一页页面高度
const pages = []
// 遍历最小单元格
// 获取单元格底部距离顶部的高度 top,以及 offsetTop
// 根据 top 值,算出该单元格的页码,放入数组 pages
$unitElements.forEach($element => {
const offsetTop = $element.offsetTop - pageOffsetTop
let pagesIndex = Math.ceil(offsetTop / peerPageHeight)
for (let i = 0; i < pagesIndex; i++) {
if (typeof pages[i] === 'undefined') {
pages[i] = [{
offsetTop: peerPageHeight * i,
top: peerPageHeight * (i + 1)
}]
}
}
const top = offsetTop + $element.offsetHeight
const pageIndex = Math.ceil(top / peerPageHeight)
// 新的一页
console.log(pagesIndex,12221)
if (pageIndex > pagesIndex) {
let peerIndex = Math.ceil($element.offsetHeight / peerPageHeight)
pages[pagesIndex - 1][0].top=offsetTop
for (let i = 0; i < peerIndex; i++) {
pages[pagesIndex + i] = [{
top: (offsetTop+peerPageHeight)>pageOffsetHeight?pageOffsetHeight:offsetTop+peerPageHeight,
offsetTop: offsetTop
}]
}
}
})
let heightIndex=0
let index=pages.length
if(pages.length&&pages[pages.length-1][0].toppageOffsetHeight?pageOffsetHeight:pages[index-1+i][0].top+peerPageHeight,
offsetTop: pages[index-1+i][0].top
}]
}
return pages
}
let eleW = ele.offsetWidth // 获得该容器的宽
// let eleH = ele.offsetHeight // 获得该容器的高
let eleH = ele.scrollHeight // 获得该容器的高
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_o - win_i)/2; // 获得滚动条长度的一半
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)
html2canvas(ele, {
dpi: 300,
useCORS: true //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
}).then(canvas => {
var contentWidth = canvas.width
var contentHeight = canvas.height
console.log('canvars宽:' + contentWidth + '高:' + contentHeight)
//一页pdf显示html页面生成的canvas高度;
var pageHeight = (contentWidth / (A4_WIDTH - 3)) * A4_HEIGHT // 这样写的目的在于保持宽高比例一致 pageHeight/canvas.width = a4纸高度/a4纸宽度// 宽度和canvas.width保持一致
//未生成pdf的html页面高度
var leftHeight = contentHeight
//页面偏移
var position = 20
var imgWidth = A4_WIDTH
var imgHeight = (A4_WIDTH / contentWidth) * contentHeight
console.log('缩放后图片宽:' + A4_WIDTH + '高:' + imgHeight)
var pageData = canvas.toDataURL("image/jpeg", 1.0)
var pdf = new JsPDF("", "pt", "a4")
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
let pages = splitPage(ele)
// console.log(JSON.stringify(pages))
//当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight - 40) {
//在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
pdf.addImage(pageData, 'JPEG', 10, 20, imgWidth - 20, imgHeight - 40);
pdf.save(pdfFileName + ".pdf")
} else if (pages.length > 1) {
console.log(pages)
pages.forEach((page, index) => {
const {
offsetTop
} = page[0]
const {
top
} = page[page.length - 1]
let img = new Image();
img.src = pageData;
//生成canvas
let canvas1 = {}
let num = 1
// if(index>0){
//占一页的高度比
num = (top - offsetTop) / ((A4_HEIGHT - 40) / ((A4_WIDTH - 20) / contentWidth))
// }
canvas1['canvas' + index] = document.createElement('canvas');
var ctx = canvas1['canvas' + index].getContext('2d');
var createw = document.createAttribute('width');
var createh = document.createAttribute('height');
createw.nodeValue = contentWidth;
createh.nodeValue = top - offsetTop;
canvas1['canvas' + index].setAttributeNode(createh);
canvas1['canvas' + index].setAttributeNode(createw);
img.onload = () => {
if (index > 0) {
pdf.addPage()
}
// if(num>1){
// let pageHeight=top-offsetTop
// while (pageHeight > 0) {
// tx.drawImage(img, 0, offsetTop, contentWidth, top, 0, 0, contentWidth, top);
// var base64Result = canvas1['canvas' + index].toDataURL("image/jpeg", 1.0)
// pdf.addImage(base64Result, 'JPEG', 10, 20, A4_WIDTH - 20, (A4_HEIGHT-40)*num)
// pdf.addImage(pageData, "JPEG", 10, position, imgWidth - 20, imgHeight)
// pageHeight -= pageHeight
// position -= (A4_HEIGHT)
// //避免添加空白页
// if (pageHeight > 0) {
// pdf.addPage()
// }
// }
// }else{
ctx.drawImage(img, 0, offsetTop, contentWidth, top, 0, 0, contentWidth, top);
var base64Result = canvas1['canvas' + index].toDataURL("image/jpeg", 1.0)
pdf.addImage(base64Result, 'JPEG', 10, 20, A4_WIDTH - 20, (A4_HEIGHT - 40) * num)
// }
if (index == pages.length - 1) {
pdf.save(pdfFileName + ".pdf")
}
}
})
} else {
// 分页
while (leftHeight > 0) {
pdf.addImage(pageData, "JPEG", 10, position, imgWidth - 20, imgHeight)
leftHeight -= pageHeight
position -= (A4_HEIGHT)
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
pdf.save(pdfFileName + ".pdf")
}
})
}
}
}