使用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;
}
相关推荐
浪裡遊25 分钟前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
滿26 分钟前
Vue3 Element Plus el-tabs数据刷新方法
javascript·vue.js·elementui
LinDaiuuj26 分钟前
判断符号??,?. ,! ,!! ,|| ,&&,?: 意思以及举例
开发语言·前端·javascript
敲厉害的燕宝36 分钟前
Pinia——Vue的Store状态管理库
前端·javascript·vue.js
Aphasia3111 小时前
react必备JavaScript知识点(二)——类
前端·javascript
玖玖passion1 小时前
数组转树:数据结构中的经典问题
前端
呼Lu噜1 小时前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
珠峰下的沙砾1 小时前
Vue3 里 CSS 深度作用选择器 :global
前端·javascript·css
航Hang*1 小时前
WEBSTORM前端 —— 第2章:CSS —— 第3节:背景属性与显示模式
前端·css·css3·html5·webstorm
wuhen_n1 小时前
CSS元素动画篇:基于当前位置的变换动画(一)
前端·css·html·css3·html5