导出为PDF加封面且分页处理dom元素分割

文章目录

正常展示页面

导出后效果

代码

组件内

js 复制代码
<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

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;
相关推荐
奇舞精选27 分钟前
在 Chrome 浏览器里获取用户真实硬件信息的方法
前端·chrome
热忱11281 小时前
elementUI Table组件实现表头吸顶效果
前端·vue.js·elementui
林涧泣2 小时前
【Uniapp-Vue3】setTabBar设置TabBar和下拉刷新API
前端
Rhys..2 小时前
Jenkins pipline怎么设置定时跑脚本
运维·前端·jenkins
易林示2 小时前
chrome小插件:长图片等分切割
前端·chrome
w(゚Д゚)w吓洗宝宝了2 小时前
单例模式 - 单例模式的实现与应用
开发语言·javascript·单例模式
zhaocarbon2 小时前
VUE elTree 无子级 隐藏展开图标
前端·javascript·vue.js
浏览器爱好者3 小时前
如何在AWS上部署一个Web应用?
前端·云计算·aws
xiao-xiang3 小时前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师3 小时前
【小游戏篇】三子棋游戏
前端·算法·游戏