vue 签名板

268 阅读1分钟

vue实现手写签名

image.png

image.png

  <div class="signature-wrap">
    <div class="img-wrap" @click="()=>{
      show=true
      initCanvas()
    }">
      <img v-if="absPrevdiv" :src="absPrevdiv" />
      <span v-else>点击签名</span>
    </div>
    <el-dialog title="签名" :visible.sync="show" width="30%" :before-close="handleClose">
      <div class="signature-contain" ref="canvasHW">
        <div class="signature-main" style="z-index: 3000">
          <canvas v-if="!disabled" ref="canvasF" class="signature" @mousedown="mouseDown" @mousemove="mouseMove"
            @mouseup="mouseUp"></canvas>
          <div v-else class="signature signature-disable"></div>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <div class="signature-btns">
          <div class="btn " @click="show=false">
            <span>取</span><span>消</span>
          </div>
          <div class="btn " @click="handleOverwrite()">
            <span>清</span><span>空</span>
          </div>
          <div class="btn btn-ok" @click="handleSure()">
            <span>确</span><span>定</span>
          </div>
        </div>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'ESignature',
  model: {
    event: 'change'
  },
  data() {
    return {
      show: false,
      points: [],
      canvasTxt: null,
      stage_info: [],
      startX: 0,
      startY: 0,
      moveY: 0,
      moveX: 0,
      isDown: false,
      strokeStyle: '#000',
      lineWidth: 2,
      absPrevdiv: ''
    }
  },

  methods: {
    handleClose() {
      this.show = false
    },
    imageToCanvas() {
      var canvas = this.$refs.canvasF
      var img = new Image()
      img.src = this.absPrevdiv
      img.onload = function () {
        var ctx = canvas.getContext('2d')
        ctx.drawImage(img, 0, 0)
      }
    },
    // 初始化Canvas
    initCanvas() {
      this.$nextTick(() => {
        let canvas = this.$refs.canvasF
        // 获取画布的高度
        canvas.height = this.$refs.canvasHW.offsetHeight - 20
        // 获取画布的宽度
        canvas.width = this.$refs.canvasHW.offsetWidth - 20
        // 创建 context 对象
        this.canvasTxt = canvas.getContext('2d')
        this.stage_info = canvas.getBoundingClientRect()
        if (this.absPrevdiv) {
          this.imageToCanvas()
        }
      })
    },
    // 鼠标按下事件 - 准备绘画
    mouseDown(ev) {
      ev = ev || event
      ev.preventDefault()
      if (ev) {
        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
      }
    },
    // 鼠标移动事件 - 开始绘画
    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.strokeStyle = this.strokeStyle
        this.canvasTxt.lineWidth = this.lineWidth
        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 (ev) {
        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
      }
    },
    // 返回
    handleGoBack() {
      this.handleOverwrite()
      this.$emit('on-back')
    },
    // 重写
    handleOverwrite() {
      this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
      this.points = []
    },
    handleSure() {
      this.absPrevdiv = this.$refs.canvasF.toDataURL()
      this.$emit('change', this.absPrevdiv)
      this.show = false
      console.log(this.absPrevdiv)
    }
  }
}
</script>

<style lang="less">
.signature-wrap {
  height: 100%;
  width: 100%;
  // padding: 0 5px

  // min-width: 60vw
  .img-wrap {
    width: 200px;
    height: 60px;
    background: #f3f3f3;
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;

    img {
      width: 100%;
      height: 100%;
    }

    // background: red
  }
}

.signature-contain {
  width: 100%;

  .signature-main {
    background: white;
    flex-direction: row-reverse;
    display: flex;
    align-items: stretch;
    height: 101%;
    overflow: scroll;
  }

  .signature-title {
    font-weight: bold;
    font-size: 18px;
    display: flex;
    padding: 0 20rpx;
    flex-direction: column;
    justify-content: center;
    height: 100vh;
    color: #333;

    span {
      transform: rotate(90deg);
    }
  }

  .signature {
    border: 1px solid #ccc;
    background: #FFF;
    margin: 10px 0;
    width: 100%;
    height: 200px;
    align-self: center; // pointer-events:none
  }

  .signature-disable {
    background: #f3f3f3;
  }


}

.signature-btns {
  display: flex;
  justify-content: space-between;

  .btn {
    padding: 5px 30px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 6px;
    cursor: pointer;
  }

  .btn-ok {
    color: #fff;
    border-color: #1890ff;
    background: #1890ff;
  }
}
</style>

使用

import ESignature from '@/components/ESignature/index.vue'
<ESignature v-model="auditForm.sigImg" />
 components: {
    ESignature
  }