移动端手写签名实现


项目需要,要在移动端实现手写签名转换成图片,需要用到canvas实现,canvas实在是没学过,只能硬着头皮上,借助万能的网络,废了几千个脑细胞,终于把功能实现了,现在记录以下,希望可以帮助其他码友

展示:
在这里插入图片描述

页面布局

<div class="sign_page"  v-show="isShowSign" @touchmove.prevent="">             
            <div class="canvas_page" >
              <div style="float:left;font-size:20px;margin-top:10px;margin-left:10px;">填写签名</div>
              <div @click="closeSign" style="float:right;margin-top:10px;margin-right:20px;"><van-icon name="close" size="30" /></div>
              <div class="handCenter">
                <canvas id="canvasMy"></canvas>
              </div>
            </div>
            <div class="button_line">
              <van-button  size="small" color="#00B9AA" style="margin-right:20px;width:90px;"  @click.stop="clearArea">重写</van-button>
              <van-button color="#00B9AA"  size="small" style="margin-right:20px;width:90px;"  @click="toNextStep">确认并提交</van-button>
            </div>
          </div>

css样式

.sign_page{
  position:fixed;
  top:0;
  left:0;
  height:100%;
  width: 100%;
  background: rgba(19, 18, 18,0.7);
  z-index: 1111;
}

  .canvas_page{
    width:80%;
    background: #ffffff;
    height:60%;
    margin-top: 90px;
    margin-left: 10%;
    box-sizing: border-box;
    overflow: hidden;
    .handCenter {
      overflow: hidden;
      // max-width:60vw;
      width: 100%;
      height:90%;
      // margin:0 auto;
       margin-top: 50px;
       box-shadow: 0 2px 4px rgba(0,0,0,.25);
      box-sizing: border-box;
    }
  }
.button_line{
    display: flex;
    justify-content: center;
    margin: 0 auto;
    width: 80%;
    align-items: center;
    background: #ffffff;
    padding:40px 0 20px 0;
  }
  /*重写的按钮*/
  .reWriteBtn{
    padding: 0.1rem 0.2rem!important;
    font-size:18px;
    text-align: center;
  }

代码实现业务逻辑

1、弹出签名弹窗时要初始化画布,设置好画布的监听器

      //填写签名
     sign(){
       this.isShowSign=true;
       this.$nextTick(() => {
        let canvas = document.getElementById('canvasMy');
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        let node = document.getElementsByClassName('handCenter')[0];
        let rect = node.getBoundingClientRect();
        let winW = rect.width;
        let winH = rect.height
        canvas.width = winW;
        canvas.height = winH;
        this.Init()
      });
     },
      Init() {
        this.isShowSign=true;
			this.canvas.addEventListener(
				'touchstart',
				(event)=> {
					if (event.targetTouches.length == 1) {
						event.preventDefault(); // 阻止浏览器默认事件,重要
						var touch = event.targetTouches[0];
						this.touchPressed = true;
						let x = event.changedTouches[0].clientX;
                        let y = event.changedTouches[0].clientY;
						//this.draw(touch.pageX - this.canvas.offsetLeft, touch.pageY - this.canvas.offsetTop, false);
            this.draw(x - this.canvas.offsetLeft, y - this.canvas.offsetTop, false);
					}
				},
				false
			);
			this.canvas.addEventListener(
				'touchmove',
				(event) =>{
					if (event.targetTouches.length == 1) {
						event.preventDefault(); // 阻止浏览器默认事件,重要
						var touch = event.targetTouches[0];
						let x = event.changedTouches[0].clientX;
                        let y = event.changedTouches[0].clientY;
						if (this.touchPressed) {
							//this.draw(touch.pageX - this.canvas.offsetLeft, touch.pageY - this.canvas.offsetTop, true);
              this.draw(x - this.canvas.offsetLeft, y - this.canvas.offsetTop, true);
						}
					}
				},
				false
			);
			this.canvas.addEventListener(
				'touchend',
				(event)=> {
					if (event.targetTouches.length == 1) {
						event.preventDefault(); // 阻止浏览器默认事件,防止手写的时候拖动屏幕,重要
						this.touchPressed = false;
					}
				},
				false
			);
    },

2、签名完成周点击确认按钮把签名转换成图片

根据各自后台的要求将签名转换成相应的格式传给后台,保存在服务器上

    //点击确认按钮
    toNextStep:debounce(function () {
      let res = this.ifDraw();
      if(res){
        this.$message.warning('请写下你的签名')
        return
      }
      this.$confirm('确认当前的签名无误且清晰?', '提示')
      .then(() => {
        this.saveImage();       
      })
      .catch(action => {
      });
    },1000),
    
	//保存为图片
	saveImage() {
		let oCanvas = document.getElementById("canvasMy");
		let imgBase64 = oCanvas.toDataURL();  
		this.imgsrc = imgBase64; 
         // let url = this.canvas.toDataURL(); //此时图片为Base64格式
         let file = this.dataURLtoFile(imgBase64);
          //此时图片为Base64格式
		const form = new FormData();
         form.append('file',file)//向formdata里面存放键值
        this.$api.uploadPictureCheck(form).then(res=>{ 
            if(res.data.success==true){
              this.signPic = res.data.filePath;
              this.sure();
            }else{
              Toast('签名上传失败')
            }
          }).catch(err=>{           
          })
			},
     //转成 File 对象将画布转为文件流,可以用于后续的上传
    dataURLtoFile(dataurl) {
      var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      // 这里的 'share.png' 是自定义的文件名
      return new File([u8arr], 'sign' + '.png',{ type: mime });
    },
	draw(x, y, isDown) {
		let ctx = this.ctx
		if (isDown) {
			ctx.beginPath();
			ctx.strokeStyle = this.strokeStyle;
			ctx.lineWidth = this.lineWidth;
			ctx.lineJoin = "round";
			ctx.moveTo(this.lastX, this.lastY);
			ctx.lineTo(x, y);
			ctx.closePath();
			ctx.stroke();
		}
		this.lastX = x; this.lastY = y;
	},
	clearArea(){
		this.ctx.setTransform(1, 0, 0, 1, 0, 0);
		this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
	},
    //判断是否绘制签名
    ifDraw(){
      var blank = document.createElement('canvas');
      blank.width = this.canvas.width;
      blank.height = this.canvas.height;

      return this.canvas.toDataURL() == blank.toDataURL();
    },
      
	//Base64格式转成图片
	dataURLtoBlob(dataurl) {
		var arr = dataurl.split(',')
		var mime = arr[0].match(/:(.*?);/)[1]
		var bstr = atob(arr[1])
		var n = bstr.length
		var u8arr = new Uint8Array(n)
		while (n--) {
			u8arr[n] = bstr.charCodeAt(n)
		}
		return new Blob([u8arr], {
			type: mime
		})
	},

这样基本就可以实现,主要难点在将签名转换成图片传给后台保存

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值