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

文章目录

  • 正常展示页面
  • 导出后效果
  • 代码

正常展示页面

在这里插入图片描述

导出后效果

在这里插入图片描述

代码

组件内

<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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/48167.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

栈粉碎原理分析

栈粉碎原理分析 源代码如下 #include <stdio.h>void function(int a, int b) {char buffer[12];gets(buffer);//long* ret (long *) ((long)buffer28);//*ret *ret 7;return; }void main() {int x;x 0;function(1,2);x 1;printf("%d\n",x); } 由解注释前…

windows C++多线程同步<3>-互斥量

windows C多线程同步&#xff1c;3&#xff1e;-互斥量 概念&#xff0c;如下图&#xff1a; 另外就是互斥对象谁拥有&#xff0c;谁释放 那么一个线程允许多次获取互斥对象吗&#xff1f; 答案是允许&#xff0c;但是申请多次就要释放多次&#xff0c;否则其他线程获取不到互…

「分享」Word文档被锁定无法编辑怎么办?4种方法解决

有没有遇到这种情况&#xff1f;打开Word文档后&#xff0c;发现文档被锁定了&#xff0c;无法输入内容&#xff0c;也无法修改&#xff0c;这很大可能是Word文档被设置了“限制编辑”。 如果Word文档被设置了“限制编辑”&#xff0c;而我们又需要编辑文档&#xff0c;可以用…

等分切割图片的方法

在做数据集的过程中&#xff0c;有时候需要将大图进行切分成小图片&#xff0c;一方面是为了满足训练需要&#xff0c;一方面是为了扩增数据集。 如下图的尺寸为5472x3648,但是我用不着这么大的图片&#xff0c;需要将图9等分 市面上也有等分切割图片的软件或者网站&#xff…

tensorRT多batch动态推理

tensorRT的多batch推理&#xff0c;导出的onnx模型必须是动态batch&#xff0c;只需在导出的时候&#xff0c;设置一个dynamic_axis参数即可。 torch.onnx.export(hybrik_model, dummy_input, "./best_model.onnx", verboseTrue, input_namesinput_names, \output_…

19 QListWidget控件

Tips: 对于列表式数据可以使用QStringList进行左移一块输入。 代码&#xff1a; //listWidget使用 // QListWidgetItem * item new QListWidgetItem("锄禾日当午"); // QListWidgetItem * item2 new QListWidgetItem("汗滴禾下土"); // ui->…

树状数组1

五分钟丝滑动画讲解 | 树状数组_哔哩哔哩_bilibili (23条消息) 树状数组(详细分析应用)&#xff0c;看不懂打死我!_树形数组_鲜果维他命的博客-CSDN博客 注意&#xff1a; 1、树状数组一般的数组一般从下标1开始赋值0作为一个边界 &#xff0c;lowbit&#xff08;0&#…

apple pencil值不值得购买?便宜的电容笔推荐

如今&#xff0c;对ipad使用者而言&#xff0c;苹果原装的Pencil系列无疑是最佳的电容笔。只是不过这款电容笔的售价&#xff0c;实在是太高了&#xff0c;一般的用户都无法入手。因此&#xff0c;在具体的使用过程中&#xff0c;如何选用一种性能优良、价格低廉的电容笔是非常…

Python数据可视化工具——Pyecharts

目录 1 简介绘图前先导包 2 折线图3 饼图4 柱状图/条形图5 散点图6 箱线图7 热力图8 漏斗图9 3D柱状图10 其他&#xff1a;配置项 1 简介 Pyecharts是一款将python与echarts结合的强大的数据可视化工具 Pyecharts是一个用于生成echarts图表的类库。echarts是百度开源的一个数据…

以智慧监测模式守护燃气安全 ,汉威科技“传感芯”凸显智慧力

城市燃气工程作为城市基建的重要组成部分&#xff0c;与城市居民生活、工业生产紧密相关。提升城市燃气服务质量和安全水平&#xff0c;也一直是政府和民众关注的大事。然而&#xff0c;近年来居民住宅、餐饮等工商业场所燃气事故频发&#xff0c;时刻敲响的警钟也折射出我国在…

大数据课程D1——hadoop的初识

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解大数据的概念&#xff1b; ⚪ 了解大数据的部门结构&#xff1b; ⚪ 了解hadoop的定义&#xff1b; ⚪ 了解hadoop的发展史&#xff1b; 一、大数据简介 1. 概述…

简要介绍 | 自回归生成:探索序列的未来之旅

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对Autoregressive Generation进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 自回归生成&#xff1a;探索序列的未来之旅 Approach - Autoregressive Conditional Generation using Transformer…

【Ajax】笔记-jsonp实现原理

JSONP JSONP是什么 JSONP(JSON With Padding),是一个非官方的跨域解决方案&#xff0c;纯粹凭借程序员的聪明才智开发出来的&#xff0c;只支持get请求。JSONP 怎么工作的&#xff1f; 在网页有一些标签天生具有跨域能力&#xff0c;比如&#xff1a;img link iframe script. …

启用、禁用员工账号

接口相关信息 controller层 /** 启用禁用员工账号* */PostMapping("/status/{status}")ApiOperation("启用禁用员工账号")public Result startOrStop(PathVariable Integer status, Long id) {log.info("启用禁用员工{}&#xff0c;{}",status,i…

Docker网络与Docker Compose服务编排

docker网络 docker是以镜像一层一层构建的&#xff0c;而基础镜像是linux内核&#xff0c;因此docker之间也需要通讯&#xff0c;那么就需要有自己的网络。就像windows都有自己的内网地址一样&#xff0c;每个docker容器也是有自己的私有地址的。 docker inspect [docker_ID]…

flask中的常用装饰器

flask中的常用装饰器 Flask 框架中提供了一些内置的装饰器&#xff0c;这些装饰器可以帮助我们更方便地开发 Web 应用。以下是一些常用的 Flask 装饰器&#xff1a; app.route()&#xff1a;这可能是 Flask 中最常用的装饰器。它用于将 URL 路由绑定到一个 Python 函数&#x…

【C++初阶】C++基础(上)——C++关键字、命名空间、C++输入输出、缺省参数、函数重载

目录 1. C关键字 2. 命名空间 2.1 命名空间的定义 2.2 命名空间的使用 3. C输入&输出 4. 缺省参数 4.1 缺省参数概念 4.2 缺省参数分类 5. 函数重载 5.1 函数重载概念 5.2 C支持函数重载的原理——名字修饰&#xff08;name Mingling&#xff09; 5.3 extern &…

【Nodejs】接口规范和业务分层

1.接口规范-RESTful架构 1.1 什么是REST REST全称是Representational State Transfer&#xff0c;中文意思是表述&#xff08;编者注&#xff1a;通常译为表征&#xff09;性状态转移。 它首次出现在2000年Roy Fielding的博士论文中&#xff0c;Roy Fielding是HTTP规范的主要编…

图像 检测 - FCOS: Fully Convolutional One-Stage Object Detection (ICCV 2019)

FCOS: Fully Convolutional One-Stage Object Detection - 全卷积一阶段目标检测&#xff08;ICCV 2019&#xff09; 摘要1. 引言2. 相关工作3. 我们的方法3.1 全卷积一阶目标检测器3.2 FCOS的FPN多级预测3.3 FCOS中心度 4. 实验4.1 消融研究4.1.1 FPN多级预测4.1.2 有无中心度…

HighTec 工程配置详解1

目录 HighTec 工程配置详解编译配置构建配置管理器编译属性编译步骤编译环境变量编译日志编译配置TriCore C CompilerTriCore C LinkerHighTec 工程配置详解 编译配置 构建配置管理器 管理器内,可以创建各种不同用途的配置项。例如用于生产工程的 ROM 配置,用于调试工程的…