vue项目导出单页pdf
提示:在vue项目中使用html2canvas+jspf导出单页(连续页不分页)pdf
安装插件
npm install --save html2canvas
npm i jspdf --save
在需要导出的vue页面中引入
import html2canvas from ‘html2canvas’;
import jsPDF from ‘jspdf’;
import { Loading } from ‘element-ui’; //导出耗时,用来提示的loading
伪html结构
<template>
<div class="main-page" id="dispatchReportPage">
<!-- 子页面A-->
<A/>
<!-- 子页面B-->
<B/>
.....
</div>
</template>
methods中导出pdf方法
exportPDF() {
this.$nextTick(() => {
// 生成的pdf只有页面窗口可见的区域,有滚动条的下面没有生成出来,需在生成PDF前,改overflow属性auto为visible
// 获取dom高度、宽度
var shareContent = document.querySelector('#dispatchReportPage');
var width = shareContent.offsetWidth / 4;
var height = shareContent.offsetHeight / 4;
let _this = this;
// eslint-disable-next-line
let loadingInstance = Loading.service({text: '正在导出,请稍等'});
html2canvas(document.getElementById('dispatchReportPage'), {
dpi: 900,
// scrolly: 0,
// width:eleW,//生成后的宽度
// height:eleH,//生成后的高度
// scrollx: -10,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
// backgroundColor: null //避免图片有白色边框
}).then((canvas) => {
var context = canvas.getContext('2d');
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var img = new Image();
img.src = pageData;
img.onload = ()=> {
// 获取dom高度、宽度
img.width = img.width / 2;
img.height = img.height / 2;
img.style.transform = 'scale(0.5)';
if (width > height) {
// 此可以根据打印的大小进行自动调节
// eslint-disable-next-line
var pdf = new jsPDF('l', 'mm', [width * 0.505, height * 0.545]);
} else {
// eslint-disable-next-line
var pdf = new jsPDF('p', 'mm', [width * 0.505, height * 0.545]);
}
pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545);
pdf.save('名字' + '.pdf');
loadingInstance.close();
};
});
});
//
},
1.采用**单页**导是由于页面由二十几页组成长度较高,且页面中子组件页面高度不固定,采用分页导出导致有的子组件页 面被截断
2.采用单页面导出整个页面,html2canvas导出是否有最大长度限制未知, pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545),中height值可适当调整
3.页面中有滚动条时需要将带有滚动条的区域去掉滚动条再导出,overflow:visible
有bug欢迎留言讨论
番外分页pdf
Vue.prototype.pageToPdf = function (ele, pdfFileName) {
console.log(ele.clientHeight, 'clientHeight ')
let loadingInstance = Loading.service({text: '正在导出,请稍等'});
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)
window.pageYOffset = 0;
document.documentElement.scrollTop = 0
document.body.scrollTop = 0;
html2canvas(ele, {
dpi: 900,
// scrolly: 0,
// width:eleW,//生成后的宽度
// height:eleH,//生成后的高度
// scrollx: -10,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
// backgroundColor: null //避免图片有白色边框
}).then(canvas => {
var contentWidth = canvas.width
var contentHeight = canvas.height
//一页pdf显示html页面生成的canvas高度;
var pageHeight = (contentWidth / 552.28) * 841.89 // 这样写的目的在于保持宽高比例一致 pageHeight/canvas.width = a4纸高度/a4纸宽度// 宽度和canvas.width保持一致
//未生成pdf的html页面高度
var leftHeight = contentHeight + 10591
//页面偏移
var position = 0
// 设置pdf的尺寸,pdf要使用pt单位 已知 1pt/1px = 0.75 pt = (px/scale)* 0.75
// 2为上面的scale 缩放了2倍
// var pdfX = ((contentWidth + 10) / 2) * 0.75
// var pdfY = ((contentHeight + 500) / 2) * 0.75 // 500为底部留白
var imgWidth = ((contentWidth + 10) / 2) * 0.75
var imgHeight = (imgWidth / contentWidth) * contentHeight
console.log(imgHeight)
//a4纸的尺寸[595.28,841.89],单位像素,html页面生成的canvas在pdf中图片的宽高
var pageData = canvas.toDataURL('image/jpeg', 1.0)
console.log(pageData, '============================')
var pdf = JsPDF('', 'px', [imgWidth , 874.2])
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
// pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
// 分页
while (leftHeight > 0) {
pdf.addImage(pageData, "JPEG", 5, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 874.8
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
pdf.save(pdfFileName + '.pdf')
this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
loadingInstance.close();
});
})
}