前端导出pdf--通过canvas画图后使用html2canvas和jsPDF导出

<template>
  <div id="el-pdf-cantainer">
    <div ref="pdfRef" class="pdf-cantainer">
      <div class="title-box">
       标题
        <div class="img-box">
          <img
            class="a-img"
            src=""
            alt="图片不能跨域"
          />
        </div>
      </div>
     
      <div class="one-title-box">
      
      </div>
    </div>
  </div>
</template>
<script>
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export default {
  data() {
    return {
      imgPath:''
    };
  },
  mounted() {
  this.computedArrFunc({skus:[]},0)
  },
  methods: {
    computedArrFunc(v, i) {
      let str = JSON.stringify(v["skus"]);
      let arr = JSON.parse(str);
      const half = Math.ceil(arr.length / 2);
      const firstHalf = arr.splice(0, half);
      const secondHalf = arr.splice(-half);
      this.drawFunc(firstHalf, secondHalf, i);
    },
    drawFunc(arr1, arr2, i) {
      // canvas事件-画图
      // 创建img数据
      const ROOMNAME = ''
      const arr = this.houseTypeList.filter(
        (item) => item.name == ROOMNAME
      );

      let image = new Image();
      image.crossOrigin = "";
      image.src = this.imgPath; // 也是考虑是否跨域
      image.setAttribute("class", "a-img");

      image.onload = () => {
        // 判断是否加载
        if (image.complete) {
          // 设置canvas
          let iw = image.width;
          let ih = image.height;
          let canvas = this.$refs.imgCanvasRef[i];
          canvas.width = this.$refs.imgCanvasRef[i].offsetWidth;
          canvas.height = this.$refs.imgCanvasRef[i].offsetHeight;
          let w = (canvas.width - iw) / 2;
          let h = canvas.height / 6;

          // canvas类型
          let ctx = canvas.getContext("2d");

          // canvas画画布
         ctx.drawImage(image, w, h, iw, ih);

          ctx.font = "22px Microsoft YaHei";
          ctx.textBaseline = "middle";
          ctx.textAlign = "left";
          let roomNameText = ctx.measureText(arr[0].name);
          ctx.fillText(
            arr[0].name,
            (canvas.width - roomNameText.width) / 2,
            canvas.height / 2.1
          );

          ctx.font = "14px Microsoft YaHei";
          ctx.textBaseline = "middle";

          const LEFT_DOT_HEIGHT_NUM =
            ih / arr1.length > 20 ? 20 : ih / arr1.length;
          const LEFT_DOT_WIDTH_NUM = 35;

          //  左边
          for (let i = 1; i <= arr1.length; i++) {
            let value = arr1[i - 1].skuName ?? "--";
            ctx.beginPath();
            ctx.fillStyle = "#000";
            ctx.arc(
              w + LEFT_DOT_WIDTH_NUM,
              h + LEFT_DOT_HEIGHT_NUM * i,
              3,
              0,
              2 * Math.PI
            );
            ctx.fill();
            ctx.strokeStyle = "#918e92";
            ctx.lineWidth = 1;
            ctx.moveTo(
              w + LEFT_DOT_WIDTH_NUM,
              h + LEFT_DOT_HEIGHT_NUM * i
            );
            ctx.lineTo(w - 100, h - 30 + LEFT_DOT_HEIGHT_NUM * i);
            ctx.lineTo(w - 250, h - 30 + LEFT_DOT_HEIGHT_NUM * i);
            ctx.textAlign = "left";
            ctx.fillStyle = "#333333";
            let text = ctx.measureText(value);
            ctx.fillText(
              value,
              w - 250 - text.width,
              h - 30 + LEFT_DOT_HEIGHT_NUM * i
            );
            ctx.stroke();
            ctx.closePath();
          }

          // 右边
          for (let i = 1; i <= arr2.length; i++) {
            let value = arr2[i - 1].skuName ?? "--";
            ctx.beginPath();
            ctx.fillStyle = "#000";
            ctx.arc(
              w + iw - 35,
              h + LEFT_DOT_HEIGHT_NUM * i,
              3,
              0,
              2 * Math.PI
            );
            ctx.fill();
            ctx.strokeStyle = "#918e92";
            ctx.lineWidth = 1;
            ctx.moveTo(w + iw - 35, h + LEFT_DOT_HEIGHT_NUM * i);
            ctx.lineTo(w + iw + 121, h - 30 + LEFT_DOT_HEIGHT_NUM * i);
            ctx.lineTo(w + iw + 250, h - 30 + LEFT_DOT_HEIGHT_NUM * i);
            ctx.textAlign = "left";
            ctx.fillStyle = "#333333";
            ctx.fillText(
              value,
              w + iw + 250,
              h - 30 + LEFT_DOT_HEIGHT_NUM * i
            );
            ctx.stroke();
            ctx.closePath();
          }
        }
      };
    },
    onDowan() {
      const target = this.$refs.pdfRef;
      html2canvas(target, { useCORS: true, tainttest: true }).then((canvas) => {
        const casle = 2
        let contentWidth = canvas.width/casle;
        let contentHeight = canvas.height/casle;
        //  一页pdf显示html页面生成的canvas高度;
        let pageHeight = (contentWidth / 592.28) * 841.89;
        //  未生成pdf的html页面高度
        let leftHeight = contentHeight;
        //  页面偏移
        let position = 0;
        //  a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        let imgWidth = 595.28;
        let imgHeight = (592.28 / contentWidth) * contentHeight;
        let pageData = canvas.toDataURL("image/jpeg", 1.0);
        //  l表示横版,p:纵向 (默认纵向)
        const pdf = new jsPDF("", "pt", [contentWidth, contentHeight]);
        pdf.addImage(pageData, "JPEG", 0, 0, contentWidth, contentHeight);
        //  有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        //  当内容未超过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操作,根据业务需求来,注意1与2不能同时存在,否则后执行的导出的pdf在wps无法打开,显示文件损坏
        // 如果需要对同一个pdf既需要本地下载,又需要发给后台,请导出两次,一次本地下载,一次发给后台
        // 1.本地下载
        pdf.save(
          ``,
          pdf
        );

        //      // 2.传给后台 文件流形式
        //      const pdfFile = pdf.output('blob');
        //      //  解决blob给文件命名问题 暂时不知道其他方法
        //      var file = new File([pdfFile], `${pdfName}.pdf`, {type: 'application/pdf', lastModified: Date.now()});
        //      formDataPDF.append('files', file);

        //      // 2. 传给后台 base64
        //      const datauri = pdf.output('dataurlstring');
        //      //  去掉前面的字符串后,就是文件的加密字符串
        //      const base64 = datauri.substring(28);
        //      //   然后把这个字符串送到后台解密

        //       //  2.传给后台
        //       // 将base64转成二进制
        //  copyDom.remove();
      });
    },
  },
};
</script>
<style lang="less" scoped>
#el-pdf-cantainer {
  width: 100%;
  .pdf-cantainer {
    h1{
      &::after{
        content: "";
        // width: 60%;
        // display: inline-block;
      }
    }
    width: 100%;
    .el-descriptions {
      height: 143px;
      overflow: auto;
      margin-top: 10px;
    }

    .title-box {
      border-bottom: 1px solid;
      text-align: center;
      height: 26px;
      position: relative;

      .img-box {
        width: 110px;
        position: absolute;
        top: 0;
        right: 0;
      }
      // text-decoration:underline
    }
   
    .one-title-box {
      margin-top: 20px;
      .zfb-img-box{
        width: 220px;
        height: 330px;
        margin: 0 auto;
      }
      // text-decoration: overline;
    }
    .h2-line {
      // font-weight: bold;
      // font-size: 16px;
      // border-top: 1px dotted;
      // position: relative;
      &::before,
      &::after {
        content: "";
        // position: absolute;
        // top: 8px;
        // border-bottom: dotted 1px;
        // display: inline-block;
        // width: 4  5%;

      }
      // &::before {
      //   left: 0;
      // }
      // &::after {
      //   right: 0;
      // }
    }
    
    margin: 0 auto;
    padding: 35px;
    .goods-item {
      background: #f0f3fc;
      height: 110px;
      margin: 10px 0;
      padding: 0 15px;
      display: flex;
      justify-content: space-around;
      align-items: center;
      .title {
        width: 175px;
      }
      .num,
      .price {
        width: 110px;
      }
    }
  }
}
</style>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值