移动端vue+canvas手写抄录拼接、Promise判断拼接图片是否加载完成、自动上传手写文字

<template>
  <div class="sign">
    <div class="copyContent">
      <div
       class="copy"
       ref="copy"
       v-for="(m,index) in copy"
       :class="{ active: currentIndex === index}"
       :key="index"
       src="m">
        {{m}}
      </div>
    </div>
    <div>
      <div class="line"></div>
      <div class="line"></div>
      <div class="line"></div>
      <div class="line"></div>
    </div>
    <div class="imglist-box" ref="imglistBox">
      <img v-for="item in imgUrlList" class="imgCanvas" :src="item" :key="item">
    </div>
    <section class="signature">
        <div class="signatureBox">
            <div class="canvasBox" ref="canvasHW">
                <canvas ref="canvasF" @touchstart='touchStart' @touchmove='touchMove' @touchend='touchEnd' @mousedown="mouseDown" @mousemove="mouseMove" @mouseup="mouseUp"></canvas>
            </div>
        </div>
    </section>
    <div class="btnBox">
        <div @click="deleteAll" class="btn1">删 除</div>
        <div @click="commitFlag && commit()" class="btn1">确 定</div>
        <div @click="commitAll" class="btn1">提 交</div>
    </div>
  </div>
</template>
<script>
// eslint-disable-line no-unused-vars
let t
export default {
  name: 'copy',
  data () {
    return {
      stageInfo: '',
      imgUrl: '',
      imgUrlList: [],
      client: {},
      points: [],
      canvasTxt: null,
      startX: 0,
      startY: 0,
      moveY: 0,
      moveX: 0,
      endY: 0,
      endX: 0,
      w: null,
      h: null,
      isDown: false,
      isViewAutograph: this.$route.query.isViews > 0,
      contractSuccess: this.$route.query.contractSuccess,
      oneWord: '你',
      index: 0,
      currentIndex: 0,
      copy: '你是一种感觉,写在夏夜的晚风中。逆风的方向,更适合飞翔我不拍千万人阻挡,只怕自己投降。常为碎事而庆祝。',
      imagistBox: 0,
      imgCanvas: 0,
      commitFlag: true
    }
  },
  mounted () {
    let canvas = this.$refs.canvasF
    canvas.height = this.$refs.canvasHW.offsetHeight - 0
    canvas.width = this.$refs.canvasHW.offsetWidth - 0
    this.canvasTxt = canvas.getContext('2d')
    this.canvasTxt.lineWidth = 6
    this.stageInfo = canvas.getBoundingClientRect()
    // 获取字体容器宽度
    this.imglistBox = this.$refs.imglistBox.clientWidth
    // 设置字体图片的宽度
    this.imgCanvas = parseInt(this.imglistBox / 13) + 'px'
  },
  methods: {
    // mobile
    touchStart (ev) {
      ev = ev || event
      ev.preventDefault()
      // eslint-disable-next-line eqeqeq
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clienX,
          y: ev.targetTouches[0].clientY
        }
        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)
      }
      // 画笔开始时,停止计时器
      // eslint-disable-next-line no-undef
      clearTimeout(t)
    },
    touchMove (ev) {
      ev = ev || event
      ev.preventDefault()
      // eslint-disable-next-line eqeqeq
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientX - this.stageInfo.left,
          y: ev.targetTouches[0].clientY - this.stageInfo.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)
      }
    },
    touchEnd (ev) {
      ev = ev || event
      ev.preventDefault()
      // eslint-disable-next-line eqeqeq
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientX - this.stageInfo.left,
          y: ev.targetTouches[0].clientY - this.stageInfo.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)
      }
      t = setTimeout(() => {
        this.commitOneWord()
      }, 1000)
    },
    // pc
    mouseDown (ev) {
      ev = ev || event
      ev.preventDefault()
      // eslint-disable-next-line no-constant-condition
      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.strokeRect(20,20,80,100);
        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.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()
      // eslint-disable-next-line no-constant-condition
      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
      }
    },
    // 重写
    overwrite () {
      this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
      this.points = []
    },
    // 确定签名
    commitOneWord () {
      this.imgUrl = this.$refs.canvasF.toDataURL('image/jpg')
      this.currentIndex = this.currentIndex + 1
      this.imgUrl = this.$refs.canvasF.toDataURL()
      // eslint-disable-line no-unused-vars
      let black = document.createElement('canvas')
      black.width = this.$refs.canvasF.width
      black.height = this.$refs.canvasF.height
      // 判断是否是空白页面
      // eslint-disable-next-line eqeqeq
      if (black.toDataURL('image/jpg') != this.imgUrl && this.imgUrlList.length < this.copy.length) {
        // 将当前画布放在imgUrlList里
        this.imgUrlList.push(this.imgUrl)
      } else {
        console.log('当前画布为空')
      }
      if (this.imgUrlList.length > 0) {
        this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
        this.points = []
      }
    },
    commit () {
      clearTimeout(t)
      this.commitFlag = false
      this.imgUrl = this.$refs.canvasF.toDataURL('image/jpg')
      // eslint-disable-line no-unused-vars
      let black = document.createElement('canvas')
      black.width = this.$refs.canvasF.width
      black.height = this.$refs.canvasF.height
      // 判断是否是空白页面
      // eslint-disable-next-line eqeqeq
      if (black.toDataURL('image/jpg') != this.imgUrl) {
        this.commitOneWord()
      } else {
        console.log('当前画布为空')
      }
    },
    deleteAll () {
      this.imgUrlList.pop()
      // eslint-disable-next-line eqeqeq
      if (this.currentIndex != 0) {
        this.currentIndex = this.currentIndex - 1
      }
    },
    // 提交
    commitAll () {
      console.log(this.imgUrlList.length)
      // eslint-disable-next-line eqeqeq
      if (this.imgUrlList.length == 51) {
        var canvas = document.createElement('canvas')
        canvas.width = 651
        canvas.height = 246
        var context = canvas.getContext('2d')
        context.rect(0, 0, canvas.width, canvas.height)
        context.fillStyle = '#fff'
        context.fill()
        // eslint-disable-line no-unused-vars
        let promiseAll = []
        // eslint-disable-line no-unused-vars
        let imgs = []
        // 当签名列表有值时
        if (this.imgUrlList.length > 0) {
          for (let i = 0; i < this.imgUrlList.length; i++) {
            // eslint-disable-next-line no-undef
            promiseAll[i] = new Promise((resolve) => {
              imgs[i] = new Image()
              imgs[i].src = this.imgUrlList[i]
              imgs[i].onload = function () {
                resolve(imgs[i])
              }
            })
          }
          Promise.all(promiseAll).then((img) => {
            for (let i = 0; i < img.length; i++) {
              if (i <= 19) {
                context.drawImage(img[i], 30 * i, 0, 50, 50)
              } else if (i > 19 && i < 39) {
                context.drawImage(img[i], 30 * (i - 20), 50, 50, 50)
              } else {
                context.drawImage(img[i], 30 * (i - 40), 100, 50, 50)
              }
            }
          })
          var base64 = canvas.toDataURL('image/jpg') // "image/jpg" 这里注意一下
          console.log(base64)
        }
      } else {
        console.log('请抄录完上述文字')
      }
    }
  }
}
</script>
<style scoped>
.line {
  border-bottom: 1px dashed #3f3f3f;
  /* height: 0.5rem;
  margin: 0 0.3rem; */
  height: 25px;
  margin: 0 10px;
}
.copyContent {
  /* margin: 0.15rem 0.25rem 0.05rem;
  font-size: 0.3rem; */
  margin: 5px 10px 5px;
  font-size: 18px;
}
.copy {
  display: inline-block;
}
.signature{
  width: 100%;
  height: 40vh;
}
.imglist-box{
  /* margin: -2.1rem 0.5rem 0.5rem 0.5rem;
  height: 2rem; */
  margin: -100.5px 2px 2px 2px;
  height: 100px;
}
.imgCanvas{
  height: 25px;
}
.resign{
  width: 14%;
  position: absolute;
  top: 0;
  right: 0;
}
.signatureBox {
  width: 80%;
  margin: 0 auto;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.canvasBox {
  width: 100%;
  align-items: center;
  box-sizing: border-box;
  flex: 1;
}
canvas {
  background-image: url('../assets/image/mi.png');
  background-position: center center;
  background-repeat: no-repeat;
  background-origin: border-box;
  background-size: 100% 100%;
}
  .btnBox{
    width: 85%;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    margin-bottom: 0.4rem;
}

.btn1{
  width: 27%;
  height: 30px;
  line-height: 30px;
  color: #fa4b31;
  border-radius: 2px;
  background: #fff;
  border: 1px solid #fa4b31;
  box-shadow: 0 0 0px 1px #fa4b31;
  font-size: 0.29rem;
  text-align: center;
}
.btnBox button:first-of-type {
  background: transparent;
  border-radius: 4px;
  height: 40px;
  width: 80px;
  font-size: 14px;
}
.btnBox button:last-of-type {
  background: #71b900;
  color: #fff;
  border-radius: 4px;
  height: 40px;
  width: 80px;
  font-size: 14px;
}
.active {
  color: red;
}
.color {
  color: #fa4b31;
}
</style>

效果图

我是在网上查看这位大神写的加上了我自己需要的功能

参考地址:vue+canvas 移动端手写签名,合并图片_XingFang666的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值