裴大头-秦可爱

裴大头-秦可爱

基于html2canvas、jspdf 实现网页打印效果

发表于 2024-08-06
裴大头
阅读量 519
更新于 2024-08-06

Vue2项目中实现将页面中指定DOM导出为PDF格式。自定义隐藏指定DOM中不想打印出来的内容。

首先是需要用到的依赖:html2canvasjspdf

首先将导出功能封装成一个按钮组件(当然如果使用频率不高就没必要,反而更方便隐藏不想打印的内容)

<template>
  <!-- 导出分析报告 -->
  <el-button :loading="exporting" :disabled="disabled" @click="exportPic">导出分析报告</el-button>
</template>

<script>
  import html2canvas from 'html2canvas';
  import JsPDF from 'jspdf'
  export default {
    name: 'exportPicButton',
    props: {
      operationClass: String,
      disabled: Boolean
    },
    data() {
      return {
        exporting: false
      }
    },
    methods: {
      /**
       * 导出分析报告
       */
      exportPic() {
        if (!this.operationClass) return;
        // 防御避免导出时重复点击,导完后才允许点击
        if (this.exporting) return;
        // 显示导出中
        this.exporting = true;
        this.$emit('before-export');
        // 截图
        this.$nextTick(() => {
          setTimeout(() => {
            const dom = document.querySelector(`.${this.operationClass}`);
            html2canvas(dom, {
              height: dom.scrollHeight,
              windowHeight: dom.scrollHeight,
              // 解决导出卡顿问题
              ignoreElements: e => {
                if (
                  e.contains(dom) ||
                  dom.contains(e) ||
                  e.tagName === 'STYLE' ||
                  e.tagName === 'LINK' ||
                  e.tagName === 'HEAD' ||
                  e.getAttribute('data-html2canvas') != null // header里面的样式不能筛掉
                ) {
                  return false;
                }
                return true;
              }
            }).then(canvas => {
              let contentWidth = canvas.width;
              let contentHeight = canvas.height;
              let pageHeight = contentWidth / 592.28 * 841.89;
              let leftHeight = contentHeight;
              let position = 0;
              let imgHeight = 592.28 / contentWidth * contentHeight;
              let pageData = canvas.toDataURL('image/jpeg', 1.0);
              let PDF = new JsPDF('', 'pt', 'a4');
              // 边距
              const margin = 20;
              // 调整图片宽度和高度以适应页面并保持比例
              let imgWidth = 595.28 - 2 * margin;
              imgHeight = imgWidth / 595.28 * imgHeight;
              if (leftHeight < pageHeight) {
                PDF.addImage(pageData, 'JPEG', margin, margin, imgWidth, imgHeight);
              } else {
                while (leftHeight > 0) {
                  PDF.addImage(pageData, 'JPEG', margin, margin + position, imgWidth, imgHeight);
                  leftHeight -= pageHeight;
                  position -= 841.89;
                  if (leftHeight > 0) {
                    PDF.addPage();
                  }
                }
              }
              // 当前时间
              const now = new Date();
              const nowStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
              PDF.save(`分析报告${nowStr}.pdf`)
              // 关闭导出中
              this.exporting = false;
            }).catch((err) => {
              // 显示按钮
              this.exporting = false;
              // todo 处理异常
              console.log(err);
            }).finally(() => {
              this.$emit('after-export');
            });
          }, 500)
        });
      }
    }
  }
</script>
javascript

组件只有一个按钮内容,props中接收的operationClass(需要打印DOM的class名称)、disabled(打印/导出按钮是否可用),emit事件有before-export(导出前要做的事情,如影响导出必须为同步)、after-export(导出后要做的事情)

使用方式:

<template>
     <div class="main" v-loading="pageLoading">
       <div class="page-title">
         <export-pic-button
           v-show="showHidden"
           size="small"
           :disabled="!canExportAnalysisReport"
           operation-class="content"
           @before-export="() =>{
              showHidden = false;
              pageLoading = true;
            }"
           @after-export="() => {
              showHidden = true;
              pageLoading = false;
            }"
         ></export-pic-button>
       </div>
       <div class="content">
         要打印的内容
         <div class="hidden" v-show="showHidden">打印时不想展示的内容</div>
       </div>
     </div>
</template>
<script>

import ExportPicButton from "@/pages/index/views/zkgl/analyse/components/ExportPicButton.vue";

export default {
  name: 'export-pic',
  components: {ExportPicButton},
  data() {
    return {
      // 是否可导出
      canExportAnalysisReport: true,
      // 按钮是否显示
      showHidden: true,
      // 页面加载中
      pageLoading: false,
    };
  },
};
</script>
js

image.png 导出PDF为分析报告2024-08-06.pdf

评论
来发一针见血的评论吧!
表情

快来发表评论吧~

推荐文章
  • JavaScript 的事件循环机制

    1点赞1评论

  • Element UI 级联选择器 el-cascader 实现懒加载和搜索功能

    1点赞0评论

  • Java 23种设计模式——适配器模式(Adapter)

    1点赞0评论

  • Vue项目代码规范

    1点赞1评论

  • Java 23种设计模式——单例模式(Singleton)

    0点赞1评论

Crafted with by Pei你看雪

小破站居然运行了 1048 天访客 26775

© 2023 Pei你看雪鲁ICP备19037910号-2