一、整体实现过程
- 为打印内容每个需要计算高度的dom节点添加同名类和唯一id
- 获取dom节点计算每个节点的高度,进行翻页
- 设置html2canvas和jspdf等参数转化为pdf
需要考虑的细节?
同名类可以使用uuidv4()生成唯一id添加到类名中方便获取,对于v-for循环的数据,需要计算高度的每个循环项需要添加唯一id
二、开始开发
1.使用dialog封装放入需要打印的内容
dialogPrint.vue
<el-dialog v-if="dialogVisible"
width="800px"
v-dialogDrag
:modal="true"
destroy-on-close
append-to-body
custom-class='batchRecordSetUpEdit-dialog-body'
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:before-close="
() => {
dialogVisible = false;
}
">
<printContent :recordId="recordId"
:reportName="reportPeoples.user_name"
:reportTime="reportTime"
:userDeptName="userDeptName">
</printContent>
<span slot="footer"
style="position: relative; z-index: 999">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary"
@click="showExportPDF = true"
v-else>导出PDF</el-button>
</span>
</el-dialog>
printContent.vue
<div class="batchRecordSetUpEdit-dialog-body scrollView-bar">
<div class="content_top"
id="content_top"
:class="[`print-content-prtin-item-${recordId}`]">
<div class="top_image">
<div style="
height:10px;"></div>
</div>
<div style="
height:10px;"></div>
<h2>工作周报</h2>
<div style="
height:20px;"></div>
</div>
<div :class="[`print-content-prtin-item-${recordId}`]"
v-for="(task,taskIndex) in project.task_list"
:id="`task_list-${taskIndex}`"
:key="taskIndex">
<div :class="[`print-content-prtin-item-${recordId}`]">
{{item.name}}
</div>
</div>
<div class="resume-container print-contrainer"></div>
</div>
2.获取dom节点计算高度并进行翻页
//导出pdf
exportPDF (callback, type) {
let ua = navigator.userAgent;
if (/firefox/i.test(ua))
return this.$alert(
"此功能暂时无法在该浏览器上使用,请更换其他浏览器使用",
"提示",
{
confirmButtonText: "确定",
callback: action => { }
}
);
// 获取所有子节点
let doms = document.getElementsByClassName(
`print-content-prtin-item-${this.recordId}`
)
// 维护一个数组,保存每个子节点的id和高度,代替doms进行增删改查操作
// 由于doms节点数组不是数组,因此通过call进行遍历
let data = Array.prototype.map.call(doms, item => {
return {
id: item.id,
height: item.offsetHeight
};
});
// dom节点的容器
let pdfDom = document.createElement("div");
pdfDom.id = "pdf";
let domHeight = 0;
let page = document.createElement("div");
page.style.position = "relative";
page.style.width = "760px";
page.style.height = "1080px";
page.style.padding = "20px";
page.style.boxSizing = "border-box";
// 遍历所有子节点
data.forEach((node, index) => {
let dom = Array.prototype.filter.call(
doms,
item => item.id == node.id
)[0];
//查看节点高度
if (domHeight + node.height < 950) {
page.appendChild(dom.cloneNode(true));
// table.appendChild(dom.cloneNode(true)); //插入表格实现合并边框
domHeight += node.height;
if (index == data.length - 1) {
// setWaterMark("内部记录,禁止外传", page, 1080, 860);
pdfDom.appendChild(page);
}
} else {
let deepdom = dom.cloneNode(true)
//获取新页面第一个tr节点
let pagefirstDom = deepdom
// 循环加入到容器中
pdfDom.appendChild(page);
page = null;
page = document.createElement("div");
page.classList.add("print-page");
page.style.width = "760px";
page.style.height = "1080px";
page.style.padding = "20px";
page.style.boxSizing = "border-box";
page.style.position = "relative";
page.appendChild(dom.cloneNode(true));
domHeight = node.height;
if (index == data.length - 1) {
pdfDom.appendChild(page);
}
}
});
let container = document.getElementsByClassName("resume-container")[0];
this.showExportPDF = false
return new Promise((resolve, reject) => {
this.getPdf("pdf", this.recordTitle, type).then(res => {
if (res) {
resolve(res)
}
})
container.removeChild(pdfDom);
if (callback) callback();
})
},
3.封装getpdf函数进行html2canvas并成功进行jspdf转换
Vue.prototype.getPdf = function(id, title,type) {
return new Promise(function(resolve,reject){
//1.html2canvas将html页面转化为图片
html2canvas(document.querySelector(`#${id}`), {
useCORS: true, //看情况选用上面还是下面的,
dpi: 1200,
scale: 3,
allowTaint: true,
taintTest: false
}).then(function(canvas) {
let contentWidth = 2280;
let contentHeight = canvas.height;
//一页pdf显示html页面生成的canvas高度;
let pageHeight = (contentWidth / 592.28) * 841.89;
//未生成pdf的html页面高度
let leftHeight = contentHeight;
//页面偏移
let position = 0;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
let imgWidth = 595.28;
let imgHeight = (595.28 / contentWidth) * contentHeight;
let pageData = canvas.toDataURL("image/jpeg", 1.0);
//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过pdf一页显示的范围,无需分页
//2.利用jspdf将图片的base64生成pdf文件
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();
}
}
}
PDF.save(title + ".pdf");
});
})
};
注:在转换过程中可能出现内容重叠之类的原因,这个需要对翻页高度或者转换html2canvas每页的高度进行调试