文章目录
- 正常展示页面
- 导出后效果
- 代码
正常展示页面
导出后效果
代码
组件内
<template>
<div>
<div>
<div class="content" id="content" style="padding: 0px 20px">
<div class="item">
<div
style="height: 200px; width: 100%; background: pink; display: none"
ref="wrap"
>
<h1>封面</h1>
</div>
</div>
<!-- 每一块dom的class类设置成item(自定义)以此处理内容分割 -->
<div class="item">
<button @click="outPutPdfFn">导出</button>
<!-- 组件 可为任意内容 -->
<el-row>
<el-col :span="12">
<Echrats indData_id="echarts" />
</el-col>
<el-col :span="12">
<Echrats indData_id="echarts1" />
</el-col>
</el-row>
</div>
<div class="item">
内容22
<!-- 组件 可为任意内容 -->
<el-row>
<el-col :span="12">
<Table />
</el-col>
<el-col :span="12">
<Table />
</el-col>
</el-row>
</div>
<div class="item">内容22
<el-row>
<el-col :span="12">
<Table />
</el-col>
<el-col :span="12">
<Table />
</el-col>
</el-row>
<Echrats indData_id="echarts3" />
</div>
<div class="item" style="padding: 20px 0">
gsd
<!-- 组件 可为任意内容 -->
<Echrats indData_id="echarts2" />
</div>
<div class="item" style="padding: 20px 0">
内容22
<!-- 组件 可为任意内容 -->
<Table style="margin-top: 40px" />
</div>
<div class="item">
gsd
<!-- 组件 可为任意内容 -->
<Table style="margin-top: 40px" />
<Echrats indData_id="echarts4" />
</div>
</div>
</div>
</div>
</template>
<script>
import Echrats from "./new_content/components/echarts.vue";
import Table from "./new_content/components/table.vue";
import getPdf from "@/utils/pdf";
export default {
components: {
Echrats,
Table,
},
methods:{
outPutPdfFn() {
let vm = this;
const A4_WIDTH = 592.28;
const A4_HEIGHT = 841.89;
// $myLoading 自定义等待动画组件,实现导出事件的异步等待交互
// this.$myLoading('正在导出pdf,请稍候。。。', true);
vm.$nextTick(() => {
// dom的id。
this.$refs.wrap.style.display = "block";
let target = document.getElementById("content");
let pageHeight = (target.scrollWidth / A4_WIDTH) * A4_HEIGHT;
// 获取分割dom,此处为class类名为item的dom
let lableListID = document.getElementsByClassName("item");
// 进行分割操作,当dom内容已超出a4的高度,则将该dom前插入一个空dom,把他挤下去,分割
for (let i = 0; i < lableListID.length; i++) {
let multiple = Math.ceil(
(lableListID[i].offsetTop + lableListID[i].offsetHeight) /
pageHeight
);
if (this.isSplit(lableListID, i, multiple * pageHeight)||i===0) {
let divParent = lableListID[i].parentNode; // 获取该div的父节点
let newNode = document.createElement("div");
newNode.className = "emptyDiv";
newNode.style.background = "#ffffff";
let _H =
multiple * pageHeight -
(lableListID[i].offsetTop + lableListID[i].offsetHeight);
newNode.style.height = _H + 30 + "px";
newNode.style.width = "100%";
let next = lableListID[i].nextSibling; // 获取div的下一个兄弟节点
// 判断兄弟节点是否存在
console.log(next);
if (next) {
// 存在则将新节点插入到div的下一个兄弟节点之前,即div之后
divParent.insertBefore(newNode, next);
} else {
// 不存在则直接添加到最后,appendChild默认添加到divParent的最后
divParent.appendChild(newNode);
}
}
}
// 传入title和dom标签,此处是 #content
// 异步函数,导出成功后处理交互
getPdf("巡检报告单-" + "000" + "-" + "嘿嘿嘿", "#content")
.then(() => {
// 自定义等待动画关闭
// this.$myLoading(false);
this.$message({
type: "success",
message: "导出成功",
});
})
.catch(() => {
// this.$myLoading(false);
this.$message({
type: "error",
message: "导出失败,请重试",
});
});
this.$refs.wrap.style.display = "none";
const arr = document.getElementsByClassName("emptyDiv");
const l = arr.length;
for (let i = l - 1; i >= 0; i--) {
if (arr?.[i] != null) {
arr?.[i]?.remove(arr[i]);
}
}
});
},
isSplit(nodes, index, pageHeight) {
// 计算当前这块dom是否跨越了a4大小,以此分割
if (
nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight &&
nodes[index + 1] &&
nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight
) {
return true;
}
return false;
},
}
};
</script>
<style lang="scss" scoped>
.item{
margin-top: 30px;
}
</style>>
jsPdf.js
// 导出页面为PDF格式
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
const getPdf = function (title, dom) {
// 注册getPdf方法,传入两个参数,此处使用了promise处理导出后的操作
/*
title: 导出文件名
dom: 需要导出dom的id
*/
return new Promise((resolve, reject) => {
html2Canvas(document.querySelector(dom), {
useCORS: true, // 由于打印时,会访问dom上的一些图片等资源,解决跨域问题!!重要
allowTaint: true // 允许跨域
}).then(function (canvas) {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
// 根据A4纸的大小,计算出dom相应比例的尺寸
let pageHeight = contentWidth / 592.28 * 841.89;
let leftHeight = contentHeight;
let position = 0;
let imgWidth = 595.28;
// 根据a4比例计算出需要分割的实际dom位置
let imgHeight = 592.28 / contentWidth * contentHeight;
// canvas绘图生成image数据,1.0是质量参数
let pageData = canvas.toDataURL('image/jpeg', 1.0);
// a4大小
let PDF = new JsPDF('', 'pt', 'a4');
// 当内容达到a4纸的高度时,分割,将一整块画幅分割出一页页的a4大小,导出pdf
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');
resolve(true);
})
.catch(() => {
reject(false);
});
});
};
export default getPdf;