vue+pdf.js + canvas 踩坑心得

最近公司做了一个项目,主要功能是把印章在PDF上拖拽定位的。

这个功能主要两个点:

  1. 块的拖拽即时显示印章内容;
  2. PDF回显(因涉及多人操作,回显包括之前人所签的最终效果)。

使用的[email protected] 读取PDF文件,通过canvas 以图像的形式回显在页面上(因为不是单纯的显示,还有很多交互,最终选择了这个方案)

开始一切都挺顺利的,拖拽计算坐标,PDF回显封装,印章属性设置。。。

PDF回显电子签章

在开发过程中没成想PDF回显深了一个大坑,开始是已经有印章不能回显,在网上搜索要改pdf.work.js源码,搜索下面这个判断,都注掉就行了

// if (data.fieldType === 'Sig') {
//      data.fieldValue = null;
//      _this3.setFlags(_util.AnnotationFlag.HIDDEN);
//    }

虽然能够显示印章了,但在翻页时会发生只显示一半颜色的情况,研究了好几天,更换pdf.js 版本、减少canvas 配置项都没成功。
突然在一次测试中发现,要是上来就把所有都渲染出来好像就没问题,随即用了一个比较low的方法,就是上来就把所有pdf都渲染DOM,但不显示出来(display:none),只有与当前页码相同的才显示,目前测试还没发现问题。

另,现有几个小问题:

  1. 布局时尽量用 padding、box-sizing: content-box;,用margin 有时取坐标数据不好控制;
  2. 因为找的例子是适配移动端的,里面有个参数window.devicePixelRatio,这个在mac 下通常为2,由于移动端用这个计算了宽度,在mac 下使用的时候基础坐标都*2了,PC 无脑改成1;

关于 window.devicePixelRatio 可以详细参考:
张鑫旭-设备像素比devicePixelRatio简单介绍

附上pdf 的例子
核心渲染pdf 的部分也是网上搜集的,根据业务再进行了修改;

pdfjs-fix-sig 只是把电子签章那块处理了,随手发布在自己的私服上了,npm 上肯定没有,正常引到的名称是 pdfjs-dist




父级引用

                
最后放上样式
@drag-block-size: 75px;
.e-sign-wrap {

  .pdf-page-btn-box {
    position: absolute;
    text-align: right;
    font-size: 12px;
    right: 0;
    z-index: 5;
    padding: 7px;
    color: #42474f;

    .input-box, .num-page-box {
      display: inline-block;
      height: 22px;
      line-height: 22px;
    }

    .input-box {
      width: 30px;
      .input-wrap {
        width: 100%;
        padding: 0 2px;
        font-size: 12px;
        border: 1px transparent solid;
        border-bottom: 1px #dddee1 solid;
        border-radius: 2px;
        color: #495060;
        text-align: right;

        &:focus {
          outline: none;
        }
      }
    }

    .num-page-box {
      vertical-align: middle;
    }
  }

  .pdf-box {
    float: left;
    font-size: 0;
    position: relative;


    .pdf-view-wrap {
      position: relative;
      display: inline-block;

      .drag-box {

        li {
          cursor: move;
          user-select: none;
          position: absolute;
          opacity: .7;
          z-index: 5;
          border: 1px dashed transparent;

          .party {
            color: #ffffff;
            height: 24px;
            line-height: 24px;
            padding-left: 5px;
            width: 100%;
            font-size: 12px;
          }

          .content {
            width: 98px;
            height: 49px;
            line-height: 18px;
            padding: 5px;
            font-size: 14px;
            text-align: center;
            display: table-cell;
            vertical-align: middle;
            word-break: break-all;

            .sign-type {
              font-size: 12px;
            }
          }

          &.drag-block {
            width: @drag-block-size;
            height: @drag-block-size;
            background-color: #cfddfb;

            .party {
              background-color: #9bbcff;
            }

            .content {
              color: #78a5ff;
            }
          }

          &.place-block {
            width: @drag-block-size;
            height: @drag-block-size;
            background-color: #ffcccc;

            .party {
              background-color: #f09494;
            }

            .content {
              color: #f09494;
              line-height: 16px;
              padding: 0;
              font-size: 12px;
            }

            //.btn-box {
            //  .btn {
            //    width: 100%;
            //  }
            //}
          }

          &.drag-block, &.place-block {
            &.checked::after {
              content: '';
              width: 100%;
              height: 100%;
              border: 2px #004CC0 solid;
              display: block;
              position: absolute;
              top: 0;
              left: 0;
              z-index: 0;
            }

            img {
              -webkit-user-drag: none;
            }
          }
          .btn-box {
            cursor: pointer;

            .btn {
              //float: left;
              width: 100%;
              font-size: 12px;
              text-align: center;
              height: 24px;
              line-height: 24px;
              background-color: #004cc0;
              color: #ffffff;
            }

          }
        }
      }

      canvas {
        width: 595px;
        height: 842px;
        //max-width: 595px;
        //max-height: 841px;
      }
    }

    .seal-place {
      display: inline-block;
      position: absolute;
      right: -25px;
      min-height: 841px;

      li {
        width: 5px;
        height: 100%;
        display: inline-block;
        border: 1px #eee solid;
        border-left: none;
      }
    }
  }
}

你可能感兴趣的:(vue.js,canvas,pdf)