项目说明:

  • 根据b站一位博主提供的源码改写了部分方便大家参考
  • git地址 https://gitee/kong-lingbin/pdf—seal-dragging

最终实现效果

需求:
凡pfd文件支持拖拽盖章最后生成文件流在重新上传上去
技术栈:vue, element-ui, jquery
步骤:

  1. 根目录html中引入
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/jqui.js"></script>
    <script type="text/javascript" src="js/pdf.js"></script>
    <script type="text/javascript" src="js/pdf.worker.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr/npm/bulma@0.9.1/css/bulma.min.css">
  1. 创建文件/组件
<template>
  <div>
    <section class="theinput">
      <span class="sealTitle">我的印章</span>
      <el-divider></el-divider>
      <div class="imageBox" v-for="item in imgList" :key="item.id" @click="imgClick(item)">
        <img class="image" :src="item.src" alt="" draggable="true">
      </div>
    </section>
    <section id="print">
      <div id="imgDiv">
      </div>
      <div v-if="imgArray.length > 0">
        <div v-for="(item, index) in imgArray" :key="index">
          <div class="signarea" :id="'signarea' + index">
            <img :class="'img' + index" :src="item" alt="" />
            <div v-if="isShow" class="zoom" @click="fangda(index)">+</div>
            <div v-if="isShow" class="tview" @click="opacity(index)"></div>
            <div v-if="isShow" class="tdeg" @click="revolve(index)"></div>
            <div v-if="isShow" class="contraction" @click="contraction(index)">-</div>
          </div>
        </div>
      </div>
    </section>
    <section class="rgh">
      <el-button @click="handleSave" type="primary" size="medium " icon="el-icon-picture-outline-round">保存模板</el-button>
    </section>
  </div>
</template>
<script>
import html2Canvas from 'html2canvas' //相当于截图操作
import JsPDF from 'jspdf' // 用于生成pdf
// a,b 为两个图片自行寻找
import a from '../../assets/1.png'
import b from '../../assets/2.png'
export default {
  data() {
    return {
      drag: false,
      imgList: [
        {
          id: 1,
          src: a
        },
        {
          id: 2,
          src: b
        }
      ],
      imgArray: [],
      deg: 0,
      signarea: "",
      isShow: true
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 签章放大
    fangda(index) {
      let signarea = document.querySelector(`#signarea${index}`)
      if (signarea.scale <= 2.5) {
        signarea.scale = signarea.scale / 1 + 0.1
      } else {
        signarea.scale = 1
      }
      signarea.style.transform = `scale(${signarea.scale})`
    },
    // 签章缩小
    contraction(index) {
      let signarea = document.querySelector(`#signarea${index}`)
      if (signarea.scale <= 1) {
        signarea.scale = signarea.scale / 1 - 0.1
      } else {
        signarea.scale = 1
      }
      signarea.style.transform = `scale(${signarea.scale})`
    },
    // 签章透明度
    opacity(index) {
      let imgInd = document.querySelector(`.img${index}`)
      if (imgInd.opacity >= 0.1) {
        imgInd.opacity = imgInd.opacity / 1 - 0.15
      } else {
        imgInd.opacity = 1
      }
      imgInd.style.opacity = `${imgInd.opacity}`
    },
    revolve(index) {
      this.deg += 15;
      let imgInd = document.querySelector(`.img${index}`)
      imgInd.style.transform = `rotate(${this.deg}deg)`
    },
    //开始拖拽事件
    onStart() {
      this.drag = true;
    },
    //拖拽结束事件
    onEnd() {
      this.drag = false;
    },
    init() {
      this.signarea = $('.signarea')
      $("#imgDiv").empty(); //清空上一PDF文件展示图
      PDFJS.cMapUrl = 'https://cdn.jsdelivr/npm/pdfjs-dist@2.0.288/cmaps/';
      PDFJS.cMapPacked = true;
      // url 地址
      PDFJS.getDocument({ url: 'http://dy-oss-bucket-prod.oss-cn-zhangjiakou.aliyuncs/ding3304434c3a141e3335c2f4657eb6378f-file/fileb903b3e2321649afa7fc2d4033b066a3_4a0b0b64a4be4e9094e1c3c2ce7e22e6.pdf?Expires=1675840126&OSSAccessKeyId=LTAI5t5pnuyi3iQHwB2wzNZs&Signature=tEp2%2BqG%2FJWFEZ%2FhpEM%2FEz525cNw%3D' }).then(function (pdf) { //PDF转换为canvas
        $("#imgDiv").css("border", "0"); //清除文本、边框
        if (pdf) {
          window.pageNum = pdf.numPages;
          $("#pagesText").text(`${pageNum}`);
          for (let i = 1; i <= pageNum; i++) {
            let canvas = document.createElement('canvas');
            canvas.id = "pageNum" + i;
            $("#imgDiv").append(canvas);
            let context = canvas.getContext('2d');
            openPage(pdf, i, context);
          }
        }
      });
      function openPage(pdfFile, pageNumber, context) {
        let scale = 2;
        pdfFile.getPage(pageNumber).then(function (page) {
          let viewport = page.getViewport(scale); // reference canvas via context
          let canvas = context.canvas;
          canvas.width = viewport.width;
          // $("#print").attr("style", "width:"+canvas.width+"px")
          canvas.height = viewport.height;
          // 记录当前canvas的width,height
          window.wi = canvas.width;
          window.he = canvas.height;
          canvas.style.width = "100%";
          canvas.style.height = "100%";
          let renderContext = {
            canvasContext: context,
            viewport: viewport
          };
          page.render(renderContext);
        });
        return
      };
    },
    // 左侧印章点击事件
    imgClick(item) {
      this.isShow = true
      this.imgArray.push(item.src)
      $(function () {
        $(".signarea").draggable();
      })
    },
    handleSave() {
      this.isShow = false
      this.conversionPdfFlow('234')
    },
    conversionPdfFlow(reportName = '文件名称') {
      return new Promise(() => {
        var title = reportName;
        html2Canvas(document.querySelector('#print'), {
          allowTaint: true,
          scale: 1.5,
        }).then((canvas) => {
          let contentWidth = canvas.width
          let contentHeight = canvas.height
          //一页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)
          let PDF = new JsPDF('', 'pt', 'a4')
          //有两个高度需要区分,一个是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()
              }
            }
          }
          let pdfData = PDF.output('datauristring')//获取base64Pdf
          console.log(pdfData,"获取base64Pdf")
        }
        )
      })
    },

  }
}
</script>

<style>
  html {
    background: #f2f6fc;
  }
  .sealTitle {
    display: block;
    text-align: center;
  }
  .imageBox {
    width: 120px;
    border: 1px solid #eee;
    margin: 0 auto;
  }
  .theinput {
    position: fixed;
    z-index: 101;
  }

  #print {
    position: relative;
    margin: 0 auto;
    z-index: 1;
    width: 794px;
  }

  .signarea {
    position: absolute;
    z-index: 100;
    top: 0;
    left: 300px;
  }

  .signarea img {
    width: 43mm;
  }

  canvas {
    margin: 0;
    padding: 0;
    margin-bottom: -6px;
  }

  .zoom,
  .tdeg,
  .tview,
  .lessen,
  .contraction {
    position: absolute;
    cursor: pointer;
    background-color: #fff;
    padding: 3px 10px;
    border-radius: 4px;
  }
  .contraction {
    bottom: 0;
    right: -30px;
  }
  .zoom {
    top: 0;
    left: -30px;
  }
  .tdeg {
    top: 0;
    right: -30px;
  }
  .tview {
    left: -30px;
    bottom: 0;
  }
  .lessen {
    right: -30px;
    bottom: 0;
  }

  .theinput {
    width: 300px;
    margin: 10px;
  }
  image {
    width: 20px;
  }
  .rgh {
    position: fixed;
    right: 100px;
    top: 20px;
  }
</style>

更多推荐

PDF文件 支持拖拽盖章最后生成PDF文件