使用html2canvas将html转pdf,由于table表的水平和竖直有滚动条导致显示不全(或者有空白)

结果:

业务:将页面右侧的table打印成想要的格式的pdf,首先遇到的问题是table表上下左右都有滚轮而html2canvas相当于屏幕截图,那滚动区域如何显示出来是个问题?

gif有点模糊,但是大致功能可以看出

可复制代码在最下面

参考文章:主要思路就是table既然原始高度宽度不对,那你在转pdf之前就把他的宽度高度还原成真实的高度宽度然后打印成pdf,最后再转成原始高度宽度。(值得注意的是画布的高度宽度也要设置,和table一样就行)

html代码:

script代码

table表上有个"导出按钮",点击就会触发handleExport函数

全部代码:

html:

html 复制代码
      <div
        ref="myContainer"
        id="fatherDiv"
        class="demo-form-inline"
        style="height: calc(100% - 120px)"
      >
        <el-table
          ref="workforceTable"
          :data="tableData"
          border
          @drop.native="drop($event)"
          @dragover.native="allowDrop($event)"
          stripe
          :span-method="objectSpanMethod"
          :cell-class-name="tableCellClassName"
          max-height="100%"
          height="100%"
          class="demo-form-inline"
          id="factTable"
        >
          <el-table-column
            prop="time"
            label="时间"
            width="70"
            align="center"
            fixed
          ></el-table-column>
          <el-table-column
            :prop="item.sectorCode"
            :label="item.sectorName"
            v-for="item in sectorList"
            :key="item.sectorCode"
            align="center"
          >
            <el-table-column
              :prop="seat.seatId"
              :label="seat.seatName"
              v-for="seat in item.seatList"
              :key="seat.seatId"
              align="center"
              min-width="102px"
            >
              <template slot-scope="scope">
                <span
                  :defProp="seat.seatId"
                  :defTime="scope.row.time"
                  :defIndex="scope.$index"
                ></span>
                <span
                  class="el-tag el-tag--light"
                  defid="scope.row[seat.seatId]"
                  v-if="scope.row[seat.seatId]"
                >
                  <!-- 姓名(班组名称) -->
                  <!-- {{ scope.row[seat.seatId]+"("+scope.row["team"+seat.seatId]+")" }} -->
                  <!-- 姓名 -->
                  {{ scope.row[seat.seatId] }}
                  <i
                    class="el-tag__close el-icon-close"
                    @click="onRemovePerson(scope.$index, seat.seatId)"
                    v-if="isManual"
                  ></i>
                </span>
              </template>
            </el-table-column>
          </el-table-column>

          <el-table-column
            :prop="seat.seatId"
            :label="seat.seatName"
            v-for="seat in seatList"
            :key="seat.seatId"
            align="center"
            min-width="102px"
          >
            <template slot-scope="scope">
              <span
                :defProp="seat.seatId"
                :defTime="scope.row.time"
                :defIndex="scope.$index"
              ></span>
              <span
                class="el-tag el-tag--light"
                defid="scope.row[seat.seatId]"
                v-if="scope.row[seat.seatId]"
              >
                <!-- 姓名(班组名称) -->
                <!-- {{ scope.row[seat.seatId]+"("+scope.row["team"+seat.seatId]+")" }} -->
                <!-- 姓名 -->
                {{ scope.row[seat.seatId] }}
                <i
                  class="el-tag__close el-icon-close"
                  @click="onRemovePerson(scope.$index, seat.seatId)"
                  v-if="isManual"
                ></i>
              </span>
            </template>
          </el-table-column>
        </el-table>
      </div>

script代码:

javascript 复制代码
    handleExport() {
      this.$nextTick(() => {
        let pdfName =
          (this.deptRegion == "TWR"
            ? "塔台"
            : this.deptRegion == "APP"
            ? "进近"
            : "区域") +
          "管制室" +
          this.$common.parseTime(this.selectedMonth, "{y}/{m}/{d}") +
          "日排班表";
        document
          .getElementsByClassName("demo-form-inline")[0]
          .classList.add("export-pdf-style");
        this.generatePDF(this.$refs.myContainer, pdfName);
      });
    },
    generatePDF(el, name) {
      let bodyWrapper = document.querySelector(
        "#factTable .el-table__body-wrapper"
      );
      let headerNode = document.querySelector(
        "#factTable .el-table__header-wrapper"
      );
      bodyWrapper.style.height = `${bodyWrapper.scrollHeight}px`;
      document.getElementById("fatherDiv").style.width = `${bodyWrapper.scrollWidth}px`;
      document.getElementById("fatherDiv").style.height = `${bodyWrapper.scrollHeight + headerNode.scrollHeight不}px`;
      setTimeout(function () {
        html2canvas(el, {
          scale: 4,
          width: bodyWrapper.scrollWidth + 60, // 为了使横向滚动条的内容全部展示,这里必须指定!!
          height: bodyWrapper.scrollHeight + headerNode.scrollHeight ,
        }).then((canvas) => {
          let contentWidth = canvas.width;
          let contentHeight = canvas.height;
          let pageHeight = (contentWidth / 592.28) * 841.89;      //一页pdf显示html页面生成的canvas高度;
          let leftHeight = contentHeight;      //未生成pdf的html页面高度
          let position = 0;          //页面偏移
          let imgWidth = 595.28;     //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
          let imgHeight = (592.28 / contentWidth) * contentHeight;
          let pageData = canvas.toDataURL("image/jpeg", 1.0);
          let pdf = new jsPDF("", "pt", "a4");
          if (leftHeight < pageHeight) {          //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            pdf.addImage(pageData, "JPEG", 5, 30, imgWidth, imgHeight);       //当内容未超过pdf一页显示的范围,无需分页
          } else {
            while (leftHeight > 0) {
              pdf.addImage(pageData, "JPEG", 5, position, imgWidth, imgHeight); //arg3-->距离左边距;arg4-->距离上边距;arg5-->宽度;arg6-->高度
              leftHeight -= pageHeight;
              position -= 841.89;
              if (leftHeight > 0) {           //避免添加空白页
                pdf.addPage();                //添加新页
              }
            }
          }
          pdf.save(`${name}.pdf`);
          document.getElementById("fatherDiv").style.width = `${100}%`;
          document.getElementById("fatherDiv").style.height = `calc(100% - 120px)`;
          document.getElementsByClassName("demo-form-inline")[0].classList.remove("export-pdf-style");
        });
      }, 200);
    },

css代码:

css 复制代码
.export-pdf-style >>> .el-table ,
.export-pdf-style >>> .el-tag{
  background: white !important;
  color: black !important;
}

.export-pdf-style >>> .el-table th,
.export-pdf-style >>> .el-table .el-table__cell {
  color: black;
  border: 1px solid black;
  background: white !important;
}
相关推荐
天天向上10247 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y22 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁29 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry29 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录31 分钟前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟31 分钟前
vue3,你看setup设计详解,也是个人才
前端
Lefan35 分钟前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson40 分钟前
青苔漫染待客迟
前端·设计模式·架构
写不出来就跑路1 小时前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui
OpenTiny社区1 小时前
盘点字体性能优化方案
前端·javascript