兼容web和h5的手写签名组件

95 阅读1分钟

公司需要在用户培训考试后签名

费话不多说,开撸

手写签字,归根到底就是对一个canvas进行操作,我们的需要也比较简单,就不要什么花里胡哨的,只需要签名, 清除这两个功能就可以,只不过需要兼容一下web端。

其他的控制笔画粗细,控制笔画颜色,笔锋,等等没有开发。

因为这些功能根本不是我们的客户所需要的

<template>
  <div class="sign-canvas">
    <canvas
      ref="canvas"
      canvas-id="signCanvas"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="touchEnd"
      @mousedown="mouseDown"
      @mousemove="mouseMove"
      @mouseup="mouseUp"
    />
    <div class="contents-buttons">
      <div class="contents-button" @click="clearCanvas">清除</div>
      <div class="contents-button" @click="saveCanvas">确定</div>
    </div>
  </div>
</template>

<script>
var canvas = null
var canvasTxt = null
var points = []
export default {
  data() {
    return {
      client: {},
      startX: 0,
      startY: 0,
      moveY: 0,
      moveX: 0,
      isDown: false
    };
  },
  mounted() {
    this.initCanvas()
  },
  methods: {
    initCanvas() {
      canvas = this.$refs.canvas// 指定canvas
      canvas.width = window.screen.availWidth - 90
      canvas.height = 400
      canvasTxt = canvas.getContext('2d')// 设置2D渲染区域
      canvasTxt.lineWidth = 3 // 设置线的宽度
      canvasTxt.lineCap = 'round'
      canvasTxt.lineJoin = 'round'
      canvasTxt.fillStyle = '#fff'
      canvasTxt.fillRect(0, 0, canvas.width, canvas.height)
    },
    // mobile
    touchStart(ev) {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length === 1) {
        const obj = {
          x: ev.touches[0].clientX - canvas.offsetLeft,
          y: ev.touches[0].clientY - canvas.offsetTop
        }
        this.startX = obj.x
        this.startY = obj.y
        canvasTxt.beginPath()
        canvasTxt.moveTo(this.startX, this.startY)
        canvasTxt.lineTo(obj.x, obj.y)
        canvasTxt.closePath()
        canvasTxt.stroke()
        points.push(obj)
      }
    },
    touchMove(ev) {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length === 1) {
        const obj = {
          x: ev.touches[0].clientX - canvas.offsetLeft,
          y: ev.touches[0].clientY - canvas.offsetTop
        }
        canvasTxt.beginPath()
        canvasTxt.moveTo(this.startX, this.startY)
        canvasTxt.lineTo(obj.x, obj.y)
        canvasTxt.stroke()
        canvasTxt.closePath()
        this.startX = obj.x
        this.startY = obj.y
        points.push(obj)
      }
    },
    touchEnd(ev) {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length === 1) {
        const obj = {
          x: ev.touches[0].clientX - canvas.offsetLeft,
          y: ev.touches[0].clientY - canvas.offsetTop
        }
        canvasTxt.beginPath()
        canvasTxt.moveTo(this.startX, this.startY)
        canvasTxt.lineTo(obj.x, obj.y)
        canvasTxt.stroke()
        canvasTxt.closePath()
        points.push(obj)
      }
    },
    // pc
    mouseDown(ev) {
      ev = ev || event
      ev.preventDefault()
      const obj = {
        x: ev.offsetX,
        y: ev.offsetY
      }
      this.startX = obj.x
      this.startY = obj.y
      canvasTxt.beginPath()
      canvasTxt.moveTo(this.startX, this.startY)
      canvasTxt.lineTo(obj.x, obj.y)
      canvasTxt.stroke()
      canvasTxt.closePath()
      points.push(obj)
      this.isDown = true
    },
    mouseMove(ev) {
      ev = ev || event
      ev.preventDefault()
      if (this.isDown) {
        const obj = {
          x: ev.offsetX,
          y: ev.offsetY
        }
        canvasTxt.beginPath()
        canvasTxt.moveTo(this.startX, this.startY)
        canvasTxt.lineTo(obj.x, obj.y)
        canvasTxt.stroke()
        canvasTxt.closePath()
        this.startY = obj.y
        this.startX = obj.x
        points.push(obj)
      }
    },
    mouseUp(ev) {
      ev = ev || event
      ev.preventDefault()
      const obj = {
        x: ev.offsetX,
        y: ev.offsetY
      }
      canvasTxt.beginPath()
      canvasTxt.moveTo(this.startX, this.startY)
      canvasTxt.lineTo(obj.x, obj.y)
      canvasTxt.stroke()
      canvasTxt.closePath()
      points.push(obj)
      this.isDown = false
    },
    // 重写
    clearCanvas() {
      canvasTxt.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
      points = []
    },
    // 确定签名
    async saveCanvas() {
      if (points.length === 0) {
        this.$toast.fail('请完成手写签名')
        return
      }
      const file = {}
      file.type = 'image/png'
      file.name = 'sign.png'
      file.content = this.$refs.canvas.toDataURL()
      const imgFile = await this.dataURLToBlob(file)
      // 上传...
    },
    dataURLToBlob(file) {
      var arr = file.content.split(',')
      const bstr = atob(arr[1])
      let n = bstr.length
      const u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], file.name, {
        type: file.type
      })
    }
  },
};
</script>

<style lang="scss">
  .sign-canvas {
   background-color: white;
  }
.contents-buttons {
    display: flex;
    justify-content: space-between;
    padding: 5px 0;
    border-top: 1px solid #ededed;
    .contents-button {
      padding: 10px 0;
      text-align: center;
      flex: 1;
      font-size: 15px;
      color: #257FFF;
    }
  }
</style>