PDF文件实现在线盖章

需求:需要实现给预览的PDF文件,盖上电子印章

  实现效果:(注:pdf文件资源和图片资源都是网上获取到的)

PDF文件实现在线盖章_第1张图片

安装插件

npm install pdfjs-dist --save

引入

import PDFJS from 'pdfjs-dist';

PDFJS.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.js';

这两个文件包含了获取、解析和展示PDF文档的方法,但是解析和渲染PDF需要较长的时间,可能会阻塞其它JS代码的运行。

PDF.js的API都会返回一个Promise,使得我们可以优雅的处理异步操作。

如果引入报错

修改参考:关于前端PDF显示和盖章(vue)_Harrietjia的博客-CSDN博客PDFhttps://www.jianshu.com/p/94cf6ddcb299https://segmentfault.com/a/1190000016963084https://blog.csdn.net/qq_38188485/article/details/104452542

使用canvas当作为预览pdf文件的画布

渲染PDF文件(一次渲染文件的所有页)

initPdf(flag) {
      let vm = this;
      var val = vm.pdfurl;
      if (val === '' || val === undefined) return;
      // 用于异步获取PDf文档,发送多个Ajax请求以块的形式下载文档。它返回一个Promise,该Promise的成功回调传递一个对象,该对象包含PDF文档的信息,该回调中的代码将在完成PDf文档获取时执行。
      PDFJS.getDocument(val)
        .then(function(pdfDoc_) {
          // 初始化pdf
          vm.pdfDoc = pdfDoc_;
          vm.pageCount = vm.pdfDoc.numPages;
          // 根据页码创建画布
          let id = '';
          let idTemplate = 'cw-pdf-';
          if (flag === 'init') {
            vm.createSeriesCanvas(vm.pdfDoc.numPages, idTemplate);
          }
          // 将pdf渲染到画布上去
          for (var i = 1; i <= vm.pdfDoc.numPages; i++) {
            id = idTemplate + i;
            vm.renderPDF(vm.pdfDoc, i, id);
          }
        })
        .catch(function(err) {
          if (err) {
            console.log(err);
            vm.throwerr(vm.pdfurl);
          }
        });
    },
    renderPDF(pdf, i, id) {
      let vm = this;
      pdf.getPage(i).then(function(page) {
        //  准备用于渲染的 canvas 元素
        var canvas = document.getElementById(id);
        var context = canvas.getContext('2d');
        var viewport = page.getViewport(vm.compuscale, vm.leftrotate);
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        // 将 PDF 页面渲染到 canvas 上下文中
        var renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        page.render(renderContext);
      });
    },
    createSeriesCanvas(num, template) {
      var id = '';
      for (var j = 1; j <= num; j++) {
        id = template + j;
        this.createPdfContainer(id, 'canvasstyle');
      }
    },
    createPdfContainer(id, className) {
      var pdfContainer = document.getElementById('pdf-container');
      var divNew = document.createElement('div');
      var canvasNew = document.createElement('canvas');
      divNew.id = 'div-' + id;
      canvasNew.id = id;
      canvasNew.className = className;
      divNew.appendChild(canvasNew);
      pdfContainer.appendChild(divNew);
    },

getPage():用于获取PDF文档中的各个页面。

getViewport():针对提供的展示比例,返回PDf文档的页面尺寸。

render():渲染PDF。

此时pdf文件就可以基本显示了。

之后实现印章的拖拽功能。

基本思路:我们在点击印章的时候,(鼠标按下)新创建一个和印章一模一样的节点(可以是克隆)并添加在pdf容器内(也就是作为pdf容器的子节点),之后移动鼠标(拖拽),移动的是这个新克隆出来的节点,此时根据移动的位置,给该信节点设置定位的像素值,鼠标抬起,取消鼠标移动事件。每个已经拖拽过去的印章还得支持改变位置,所以每个新戈隆的节点,需要添加对应的事件;每个拖拽的印章还需要计算边界值。

数据源data:

data() {
    return {
      cloneDragSeal: null,
      draggedSeal: null,
      scrollTop: 0,
      dragSealList: null,
      sealList: [
        {
          url: require('../../../assets/images/yinzhang1.png'),
          id: 'seal1'
        },
        {
          url: require('../../../assets/images/yinzhang2.png'),
          id: 'seal2'
        }
      ],
      pdfurl:
        'https://dakaname.oss-cn-hangzhou.aliyuncs.com/file/2018-12-28/1546003237411.pdf', // pdf链接地址
      pdfDoc: null, // pdfjs 生成的对象
      pageNum: 1, //
      pageRendering: false,
      pageNumPending: null,
      compuscale: 1, // 放大倍数
      leftrotate: 0,
      scale: 1.6, // 放大倍数  相当于初始倍数
      pageNumC: 0, // 当前页数
      pageCount: 0, // 总页数
      gotopageNum: '', // 跳转到指定的页面
      // maxscale: 2, //最大放大倍数
      // minscale: 0.8, //最小放大倍数
      isready: false
    };
  },

印章渲染:

 

给印章添加事件

let bgDom = document.getElementsByClassName('bg_mask')[0];
bgDom.addEventListener('scroll', this.scrollFn);

    sealAddEvent() {
      this.dragSealList = document.getElementsByClassName('drag_seal');
      [...this.dragSealList].forEach((item) => {
        // console.log(item.getAttribute('sealId'),'item');
        item.addEventListener('mousedown', (e) => {
          this.itemMouseDownFn({ e: e, id: item.getAttribute('sealId') });
        });
        // item.addEventListener('mouseup', (e) => {
        //   this.itemMouseupFn({ e: e, id: item.getAttribute('sealId') });
        // });
      });
    },

事件函数定义

itemMouseupFn(e) {
      if (!this.cloneDragSeal) {
        return false;
      }
      document.removeEventListener('mousemove', this.signmouseMve, false);
      let pdfContainer = document.getElementById('pdf-container');
      // 找边界值
      let left = this.cloneDragSeal.style.left.replace('px', '');
      if (
        left < 0 ||
        e.clientX > pdfContainer.offsetLeft + pdfContainer.clientWidth
      ) {
        this.cloneDragSeal && pdfContainer.removeChild(this.cloneDragSeal);
      }
      this.cloneDragSeal = null;
    },
    draggedSealOverFn(e) {
      let nextSibling = e.target.nextSibling;
      if (nextSibling) nextSibling.style.display = '';
    },
    draggedSealOutFn(e) {
      let nextSibling = e.target.nextSibling;
      if (nextSibling) nextSibling.style.display = 'none';
    },
    draggedSealUpFn(e) {
      if (!this.draggedSeal) {
        return false;
      }
      document.removeEventListener('mousemove', this.draggedSealMove, false);
      let pdfContainer = document.getElementById('pdf-container');
      // 找边界值
      let left = this.draggedSeal.style.left.replace('px', '');
      if (
        left < 0 ||
        e.clientX > pdfContainer.offsetLeft + pdfContainer.clientWidth
      ) {
        this.draggedSeal && pdfContainer.removeChild(this.draggedSeal);
      }
      this.draggedSeal = null;
    },
    draggedSealDownFn(e) {
      this.draggedSeal = e.target.parentNode;
      console.log('draggedSealDownFn', e.target.parentNode);
      document.addEventListener('mousemove', this.draggedSealMove, false);
    },
    // 已经拖拽过去的印章 移动事件
    draggedSealMove(e) {
      e.preventDefault();
      let pdfContainer = document.getElementById('pdf-container');
      this.draggedSeal.style.position = 'absolute';
      // this.draggedSeal.style.top =
      //   ((e.clientY -
      //     pdfContainer.offsetTop -
      //     this.draggedSeal.clientHeight / 2 +
      //     this.scrollTop -
      //     108) /
      //     pdfContainer.clientHeight) *
      //     100 +
      //   '%';
      this.draggedSeal.style.top =
        e.clientY -
        pdfContainer.offsetTop -
        this.draggedSeal.clientHeight / 2 -
        108 +
        this.scrollTop +
        'px';
      this.draggedSeal.style.left =
        e.clientX -
        pdfContainer.offsetLeft -
        this.draggedSeal.clientWidth / 2 +
        'px';
    },
    // 待拖拽印章的  鼠标按下事件函数
    itemMouseDownFn(obj) {
      console.log('按下');
      let e = obj.e || window.event;
      e.preventDefault();
      // 鼠标 按下 开始移动
      // 1、原印章不变  新创建一个印章(克隆)
      this.cloneDragSeal = e.currentTarget.cloneNode(true);
      let delBtn = document.createElement('div');
      delBtn.innerText = 'X';
      delBtn.style.position = 'absolute';
      delBtn.style.top = 0;
      delBtn.style.right = 0;
      delBtn.style.display = 'none';
      delBtn.addEventListener('click', this.sealDelFn);

      this.cloneDragSeal.appendChild(delBtn);
      this.cloneDragSeal.addEventListener('mousedown', this.draggedSealDownFn);
      this.cloneDragSeal.addEventListener('mouseup', this.draggedSealUpFn);
      this.cloneDragSeal.addEventListener('mouseover', this.draggedSealOverFn);
      this.cloneDragSeal.addEventListener('mouseout', this.draggedSealOutFn);
      let pdfContainer = document.getElementById('pdf-container');
      this.cloneDragSeal.className = 'dragged_seal';
      pdfContainer.appendChild(this.cloneDragSeal);
      document.addEventListener('mousemove', this.signmouseMve, false);
      document.addEventListener('mouseup', this.itemMouseupFn, false);
    },
    scrollFn(e) {
      this.scrollTop = e.target.scrollTop;
    },
    signmouseMve(e) {
      // let e = e || window.event;
      e.preventDefault();
      let pdfContainer = document.getElementById('pdf-container');

      this.cloneDragSeal.style.position = 'absolute';
      // left:  鼠标点击位置 - 当前页码pdf的offsetLeft
      // top:  鼠标点击位置 - header
      this.cloneDragSeal.style.top =
        e.clientY -
        pdfContainer.offsetTop -
        this.cloneDragSeal.clientHeight / 2 -
        108 +
        this.scrollTop +
        'px';
    },

至于和后端交互上的设计,还在实验中,请稍后。

你可能感兴趣的:(【vue-插件,elementui】,javascript,前端)