vue canvas实现手写签字

小编最近的项目与合同有关,与合同有关就避免不了合同的签署,自然而然就需要搞个签名版啦,废话少说,上代码比较实在。

sign.vue

<template>
  <div class="signHandle">
    <canvas
      ref="signHandle"
      class="canvas"
      id="canvas"
      @touchstart="drawStart"
      @touchmove="drawing"
      @touchend="draeEnd"
    >
    </canvas>
    <div class="btn-box">
      <span class="clear-btn" @click.stop="clearSign">重置</span>
      <span class="submit-btn" @click.stop="saveSign">提交</span>
    </div>
  </div>
</template>
<script>
const { clientWidth, clientHeight } = document.documentElement;
export default {
  props: {
    //canvas 宽度
    canvasWidth: {
      type: Number,
      default: clientWidth,
    },
    //canvas 高度
    canvasHeight: {
      type: Number,
      default: clientHeight,
    },
    //canvas 背景色
    canvasBackground: {
      type: String,
      default: "#fff",
    },
    //线条颜色
    lineColor: {
      type: String,
      default: "#000",
    },
    //线条宽度
    lineWidth: {
      type: Number,
      default: 3,
    },
    //线条两端形状
    lineRound: {
      type: String,
      default: "round", //圆形
    },
  },
  data() {
    return {
      direction: false, //屏幕方向  true:横屏  false:竖屏
      el: "", //canvas dom
      ctx: "", //canvas内容
    };
  },
  created() {
    this.initPhoneDirection();
  },
  mounted() {
    this.draw();
  },
  methods: {
    /**
     * 判断当前手机为竖屏还是横屏
     */
    initPhoneDirection() {
      window.addEventListener(
        "onorientationchange" in window ? "oorientationchange" : "resize",
        () => {
          if (window.orientation === 180 || window.orientation === 0) {
            this.direction = false;
            this.draw();
          }
          if (window.orientation === 90 || window.orientation === -90) {
            this.direction = true;
            this.draw();
          }
        },
        false
      );
    },
    /**
     * 添加绘制线
     */
    draw() {
      document.addEventListener("touchmove", (e) => e.preventDefault(), {
        passive: false,
      });
      this.el = this.$refs.signHandle;
      this.initCanvas();
    },
    /**
     * 初始化canvas配置
     */
    initCanvas() {
      this.el.width = this.canvasWidth;
      this.el.height = this.canvasHeight;
      this.ctx = this.el.getContext("2d");
      this.setCanvas();
    },
    /**
     * canvas配置
     */
    setCanvas() {
      this.ctx.fillStyle = this.canvasBackground;
      //绘制矩形
      if (this.direction) {
        this.ctx.fillRect(0, 0, this.canvasHeight, this.canvasWidth);
      } else {
        this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
      }
      //设置线条颜色
      this.ctx.strokeStyle = this.lineColor;
      //设置线条宽度
      this.ctx.lineWidth = this.lineWidth;
      //设置线条两端形状
      this.ctx.lineCap = this.lineRound;
    },
    /**
     * 开始绘制
     */
    drawStart(e) {
      this.ctx.beginPath();
      this.ctx.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
    },
    /**
     * 绘制过程
     */
    drawing(e) {
      this.ctx.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
      this.ctx.stroke();
    },
    /**
     * 绘制结束
     */
    drawEnd(e) {
      this.ctx.closePath();
    },
    /**
     * 重置
     */
    clearSign() {
      this.initCanvas();
    },
    /**
     * 提交
     */
    saveSign() {
      const imagesBase64 = this.el.toDataURL();
      console.log("imagesBase64", imagesBase64);
    },
  },
};
</script>
<style lang="scss" scoped>
.signHandle {
  width: 100%;
  canvas {
    display: blick;
  }
  .btn-box {
    width: 100%;
    display: flex;
    justify-content: space-between;
    span {
      display: block;
      width: 50%;
      height: 44px;
      text-align: center;
      line-height: 44px;
      color: #333;
      background: #fff;
    }
    .submit-btn {
      color: #fff;
      background: #fa5050;
    }
  }
}
</style>

在开发过程中,小编发现了一个问题,不知道有没有童鞋遇到,问题:只要canvas或canvas的父级或canvas的父级的父级,总而言之,只要canvas设置了定位,无论是什么定位,只要存在偏移,绘制就会出错,也不能说出错,是下笔的地方与实际绘制出的地方就会偏移设置定位偏移的量,听起来有些拗口,假设,小编原本在(10,10)坐标下笔开始绘制的,但是捏,小编设置定位距离顶部10px,那么绘制的时候,它可能就是从(10,20)坐标开始绘制的。小编猜测,是设置定位之后,x轴和y轴改变了,导致坐标都改变了导致的。小编想了个较笨的解决方案,就是,如果距离左右有偏移,在moveTo和lineTo的x轴坐标就需要进行相应的加减,如果是距离上下有偏移,则y轴坐标就需要进行相应的加减,至于加减多少就需要自己调试了;如果有偏移,该组件就无法进行通用了,但如果没有偏移,这个组件是通用的哦~希望对各位同学有帮助。


版权声明:本文为lavendersue原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。