使用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;
}
相关推荐
低代码布道师1 小时前
第二部分:网页的妆容 —— CSS(下)
前端·css
一纸忘忧1 小时前
成立一周年!开源的本土化中文文档知识库
前端·javascript·github
涵信2 小时前
第九节:性能优化高频题-首屏加载优化策略
前端·vue.js·性能优化
前端小巷子2 小时前
CSS单位完全指南
前端·css
SunTecTec3 小时前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
拉不动的猪4 小时前
前端常见数组分析
前端·javascript·面试
小吕学编程4 小时前
ES练习册
java·前端·elasticsearch
Asthenia04124 小时前
Netty编解码器详解与实战
前端
袁煦丞4 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛5 小时前
vue组件间通信
前端·javascript·vue.js