电子签名功能 vue

@mousedown=“mouseDown”
@mousemove=“mouseMove”
@mouseup=“mouseUp” 为pc端需求
@touchstart=“touchStart”
@touchmove=“touchMove”
@touchend=“touchEnd” 为移动端需求
将canvas转换成base64位编码格式的图片,压缩图片后,可将值进行异步请求

<template>
  <div class="signatureBox">
    <div class="visaDetailTop">
      <p class="visaTitle">电子签名</p>
    </div>
    <div class="canvasBox" ref="canvasHW">
      <canvas
        @touchstart="touchStart"
        @touchmove="touchMove"
        @touchend="touchEnd"
        ref="canvasF"
        @mousedown="mouseDown"
        @mousemove="mouseMove"
        @mouseup="mouseUp"
      ></canvas>
      <div class="btnBox">
        <button @click="overwrite">重写</button>
        <button @click="sunmitWrite">提交签名</button>
      </div>
    </div>
  </div>
</template>
<script>

export default {
  name: "",
  data() {
    return {
      points: [],
      canvasTxt: null,
      stage_info: [],
      startX: 0,
      startY: 0,
      moveY: 0,
      moveX: 0,
      endY: 0,
      endX: 0,
      w: null,
      h: null,
      isDown: false,
      X: [],
      Y: []
    };
  },
  created() {},
  mounted() {
    let canvas = this.$refs.canvasF;
    canvas.height = this.$refs.canvasHW.offsetHeight - 60;
    canvas.width = this.$refs.canvasHW.offsetWidth - 10;
    this.canvasTxt = canvas.getContext("2d");
    this.stage_info = canvas.getBoundingClientRect();
    this.canvasTxt.lineWidth = 4;
  },
  components: {},
  methods: {
    mouseDown(ev) {
      ev = ev || event;
      ev.preventDefault();
      if (1) {
        let obj = {
          x: ev.offsetX,
          y: ev.offsetY
        };
        this.startX = obj.x;
        this.startY = obj.y;
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.points.push(obj);
        this.isDown = true;
      }
    }, //移动设备事件

    touchStart(ev) {
      console.log("touchStart");
      ev = ev || event;
      ev.preventDefault();
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientX - this.stage_info.left,
          y: ev.targetTouches[0].clientY - this.stage_info.top
        };
        this.startX = obj.x;
        this.startY = obj.y;
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.points.push(obj);
      }
    }, //电脑设备事件

    mouseMove(ev) {
      ev = ev || event;
      ev.preventDefault();
      if (this.isDown) {
        let obj = {
          x: ev.offsetX,
          y: ev.offsetY
        };
        this.moveY = obj.y;
        this.moveX = obj.x;
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.startY = obj.y;
        this.startX = obj.x;
        this.points.push(obj);
      }
    }, //移动设备事件

    touchMove(ev) {
      console.log("touchMove");
      ev = ev || event;
      ev.preventDefault();
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientX - this.stage_info.left,
          y: ev.targetTouches[0].clientY - this.stage_info.top
        };
        this.moveY = obj.y;
        this.moveX = obj.x;
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.startY = obj.y;
        this.startX = obj.x;
        this.points.push(obj);
      }
    }, //电脑设备事件

    mouseUp(ev) {
      ev = ev || event;
      ev.preventDefault();
      if (1) {
        let obj = {
          x: ev.offsetX,
          y: ev.offsetY
        };
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.points.push(obj);
        this.points.push({ x: -1, y: -1 });
        this.isDown = false;
      }
    }, //移动设备事件

    touchEnd(ev) {
      console.log("touchEnd");
      ev = ev || event;
      ev.preventDefault();
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientX - this.stage_info.left,
          y: ev.targetTouches[0].clientY - this.stage_info.top
        };
        this.canvasTxt.beginPath();
        this.canvasTxt.moveTo(this.startX, this.startY);
        this.canvasTxt.lineTo(obj.x, obj.y);
        this.canvasTxt.stroke();
        this.canvasTxt.closePath();
        this.points.push(obj);
        this.points.push({ x: -1, y: -1 });
      }
    }, 
    //重写
    overwrite() {
      this.canvasTxt.clearRect(
        0,
        0,
        this.$refs.canvasF.width,
        this.$refs.canvasF.height
      );
      this.points = [];
      this.Y = [];
      this.X = [];
    },
    //提交图片
    sunmitWrite() {
      this.points.map(item => {
        this.X.push(item.x);
        this.Y.push(item.y);
      });
      /**
       * 签名所辐射的区域如果小于总屏幕的1/4,则签名太小,重新签名
       */
      let baseAcreage =
        (Math.max.apply(null, this.X) - Math.min.apply(null, this.X)) *
        (Math.max.apply(null, this.Y) - Math.min.apply(null, this.Y));
         if (baseAcreage == Infinity) {
                alert("请签名");
                return
            }
      let canvasAcreage = this.$refs.canvasF.width * this.$refs.canvasF.height;
      if (canvasAcreage / baseAcreage >= 4) {
        alert("亲,签名太小啦,请重新签名嘛!!!");
        this.overwrite();
      } else {
        let baseImg = this.$refs.canvasF.toDataURL();
        this.dealImage(baseImg, 200, callback => {
          /**
           * 200为base64转码后,图片的宽度大小
           */
          console.log(callback, "在这里提交数据");
        });
      }
    },
    //压缩图片
    dealImage(base64, w, callback) {
      var newImage = new Image();
      var quality = 0.6; //压缩系数0-1之间
      newImage.src = base64;
      newImage.setAttribute("crossOrigin", "Anonymous"); //url为外域时需要
      var imgWidth, imgHeight;
      newImage.onload = function() {
        imgWidth = this.width;
        imgHeight = this.height;
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        if (Math.max(imgWidth, imgHeight) > w) {
          if (imgWidth > imgHeight) {
            canvas.width = w;
            canvas.height = (w * imgHeight) / imgWidth;
          } else {
            canvas.height = w;
            canvas.width = (w * imgWidth) / imgHeight;
          }
        } else {
          canvas.width = imgWidth;
          canvas.height = imgHeight;
          quality = 0.6;
        }
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
        var base64 = canvas.toDataURL("image/png", quality); //压缩语句
        // 如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定
        // while (base64.length / 1024 > 150) {
        // 	quality -= 0.01;
        // 	base64 = canvas.toDataURL("image/png", quality);
        // }
        // // 防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑
        // while (base64.length / 1024 < 50) {
        // 	quality += 0.001;
        // 	base64 = canvas.toDataURL("image/png", quality);
        // }
        callback(base64);
      };
    }
  }
};
</script>

<style scoped>
.signatureBox {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
  background: #fff;
  z-index: 100;
  display: flex;
  flex-direction: column;
}
.visaDetailTop {
  width: 100%;
  padding: 5px;
  box-sizing: border-box;
  z-index: 2;
  border-bottom: 1px solid #e5e5e5;
}
.visaDetailTop p {
  margin: 0px;
  text-align: center;
  color: #000;
  font-size: 1em;
}
p.visaTitle {
  width: 100%;
  text-align: center;
  font-size: 1.2em;
}
.btnBack {
  display: block;
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  z-index: 1;
  background: transparent;
  border-color: transparent;
  outline: none;
}

.btnDaoHang {
  display: block;
  position: absolute;
  left: 0px;
  top: 0px;
  height: 2.2em;
  width: 2em;
  z-index: 1;
  background: transparent;
  border-color: transparent;
  outline: none;
}

.visaDetailTop p span {
  color: #fff;
  font-size: 1.2em;
}
.canvasBox {
  padding: 10px 5px;
  padding-top: 2px;
  box-sizing: border-box;
  flex: 1;
}
canvas {
  border-bottom: 1px solid #e5e5e5;
}
.btnBox {
  height: 30px;
  padding: 5px;
  text-align: right;
  line-height: 30px;
}

.btnBox button:first-of-type {
  border: 1px solid #71b900;
  background: transparent;
  border-radius: 4px;
  padding: 5px 10px;
}
.btnBox button:last-of-type {
  border: 1px solid #71b900;
  background: #71b900;
  color: #fff;
  border-radius: 4px;
  padding: 5px 10px;
}
@media only screen and (min-width: 750px) {
  .signatureBox {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100%;
    min-height: 100%;
    box-sizing: border-box;
    overflow: visible;
  }
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值