vue+canvas实现移动端手写签名


Posted in Javascript onMay 21, 2020

本文实例为大家分享了vue+canvas实现移动端手写签名的具体代码,供大家参考,具体内容如下

<template>
 <div class="sign">
  <div class="header">
    <i class="el-icon-arrow-left backImg" @click="goBack"></i>
    <span class="title">个人签名</span>
  </div>
  <section class="signature">
    <div class="signatureBox">
      <div class="canvasBox" ref="canvasHW">
        <canvas ref="canvasF" class="canvasStyle" @touchstart='touchStart' @touchmove='touchMove' @touchend='touchEnd' @mousedown="mouseDown" @mousemove="mouseMove" @mouseup="mouseUp"></canvas>
      </div>
    </div>
  </section>
  <div class="btnBox">
    <div @click="overwrite" class="btn1">重置</div>
    <div @click="commit" class="btn1">确定</div>
  </div>
  <div class="imglist-box" :style="imgUrlList.length>0 ? 'border: 1px solid #d9d9d9;' : ''">
   <img v-for="i in imgUrlList" class="imgCanvas" :src="i">
   <img v-show="imgUrlList.length>0" src="../../assets/img/signdelete.png" class="resign" @click="deleteAll">
  </div>
  <div class="tijiao-box">
   <button @click="commitAll" class="tijiao">提 交</button>
  </div>
 </div>
</template>
<script>
import { Bus } from '@/utils'
export default {
 name:'personsign',
 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,
   }
  },
  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 = 4
   this.stageInfo = canvas.getBoundingClientRect()
  },
  methods: {
   goBack(){
    this.$router.go(-1)
    // session.clear()
   },
   //mobile
   touchStart(ev) {
    ev = ev || event
    ev.preventDefault()
    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)
    }
   },
   touchMove(ev) {
    ev = ev || event
    ev.preventDefault()
    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()
    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)
    }
   },
   //pc
   mouseDown(ev) {
    ev = ev || event
    ev.preventDefault()
    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()
    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 = []
   },
   //确定签名
   commit() {
    this.imgUrl=this.$refs.canvasF.toDataURL();
    this.imgUrlList.push(this.imgUrl)
    if(this.imgUrlList.length>0){
     this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
     this.points = []
    }
   },
   deleteAll(){
    this.imgUrlList = []
   },
   // 提交签名给前一页
   commitAll(){
    // 用canvas合并多张图片的base64为一张图的base64
    var canvas = document.createElement("canvas");
    canvas.width = 75*this.imgUrlList.length;
    canvas.height = 100;
    var context = canvas.getContext("2d");
 
    context.rect(0 , 0 , canvas.width , canvas.height);
    context.fillStyle = "#fff";
    context.fill();
 
    var myImage = new Image();
    myImage.crossOrigin = 'Anonymous';
    // 当签名列表有值时
    if(this.imgUrlList.length>0){
     for(let i = 0;i<this.imgUrlList.length;i++){
      myImage.src = this.imgUrlList[i]
      // 多张图片绘制成一张图片
      context.drawImage(myImage , 50*i , 0 , 75 , 75); //context.drawImage(img,x,y,width,height);
      // context.font = "60px Courier New";
      // context.fillText("我是文字",350,450);
     }
     var base64 = canvas.toDataURL("image/jpg"); //"image/jpg" 这里注意一下
     this.$router.go(-1) //要在bus之前写不然值传不回去
     setTimeout(() => {
      Bus.$emit('signImage',base64) //签名base64传给前一页
     }, 300)
    }
   }
  },
  beforeDestroy(){
   // 销毁bus
   Bus.$off()
  }
}
</script>
<style scoped lang="scss">
// 签名样式很重要,会影响触点位置
.sign{
  width: 100%;
  min-height: 100vh;
  position: relative;
  .header{
   margin-bottom: 20px;
  }
  .tijiao-box{
    width: 100%;
    text-align: center;
  }
  .tijiao{
    width: 90%;
    height: 84px;
    color: #fff;
    border-radius: 2px;
    background: #fa4b31;
    box-shadow: 0 0 0px 1px #fa4b31;
    font-size: 30px;
 
   }
}
.signature{
 width: 100%;
 height: 50vh;
}
.imglist-box{
 width: 90%;
 margin: 0 auto;
 margin-bottom: 20px;
 position: relative;
}
.imgCanvas{
 width: 150px;
 height: 150px;
}
.resign{
 width: 14%;
 position: absolute;
 top: 0;
 right: 0;
}
 .signatureBox {
  width: 90%;
  margin: 0 auto;
  height: calc(100% - 50px);
  box-sizing: border-box;
  overflow: hidden;
  background: #fff;
  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/img/signbg.png');
  background-position: center center;
  background-repeat: no-repeat;
  background-origin: border-box;
  background-size: 100% 100%;
 }
 .btnBox{
  width: 90%;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
  .btn1{
   width: 46%;
   height: 84px;
   line-height: 84px;
   color: #fa4b31;
   border-radius: 2px;
   background: #fff;
   border: 1px solid #fa4b31;
   box-shadow: 0 0 0px 1px #fa4b31;
   font-size: 30px;
   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;
 }
</style>

vue+canvas实现移动端手写签名

vue+canvas实现移动端手写签名

vue+canvas实现移动端手写签名

重置就是清除田字格当前字,确定就将字保存为一张图片base64排列在列表。

重签就是删除列表所有图片,提交就是将多张图合并为一张且传给前一页显示。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript this 的一些学习总结
Aug 31 Javascript
Jquery选择子控件&quot;大于号&quot;和&quot; &quot;区别介绍及使用示例
Jun 25 Javascript
JS实现黑客帝国文字下落效果
Sep 01 Javascript
js实现无限级树形导航列表效果代码
Sep 23 Javascript
完美的js图片轮换效果
Feb 05 Javascript
Angular 2 ngForm中的ngModel、[ngModel]和[(ngModel)]的写法
Jun 29 Javascript
vue自定义filters过滤器
Apr 26 Javascript
详解Bootstrap 学习(一)入门
Apr 12 Javascript
微信小程序自定义toast组件的方法详解【含动画】
May 11 Javascript
Layui事件监听的实现(表单和数据表格)
Oct 17 Javascript
2020京东618叠蛋糕js脚本(亲测好用)
Jun 02 Javascript
vue实现表格合并功能
Dec 01 Vue.js
基于canvas实现手写签名(vue)
May 21 #Javascript
jQuery实现移动端笔触canvas电子签名
May 21 #jQuery
js cavans实现静态滚动弹幕
May 21 #Javascript
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
May 21 #Javascript
JavaScript实现HSL拾色器
May 21 #Javascript
js实现拾色器插件(ColorPicker)
May 21 #Javascript
原生js实现日期选择插件
May 21 #Javascript
You might like
PHP转换IP地址到真实地址的方法详解
2013/06/09 PHP
php像数组一样存取和修改字符串字符
2014/03/21 PHP
php单链表实现代码分享
2016/07/04 PHP
php compact 通过变量创建数组
2016/11/15 PHP
innerText和innerHTML 一些问题分析
2009/05/18 Javascript
javascript的onchange事件与jQuery的change()方法比较
2009/09/28 Javascript
关于js内存泄露的一个好例子
2013/12/09 Javascript
javascript内置对象arguments详解
2014/03/16 Javascript
ext中store.load跟store.reload的区别示例介绍
2014/06/17 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
2015/11/25 Javascript
onclick和onblur冲突问题的快速解决方法
2016/04/28 Javascript
基于jquery实现图片放大功能
2016/05/07 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
图文讲解vue的v-if使用方法
2019/02/11 Javascript
JavaScript实现图片的放大缩小及拖拽功能示例
2019/05/14 Javascript
vue 验证两次输入的密码是否一致的方法示例
2020/09/29 Javascript
vue3使用vue-count-to组件的实现
2020/12/25 Vue.js
Python EOL while scanning string literal问题解决方法
2020/09/18 Python
Python计时相关操作详解【time,datetime】
2017/05/26 Python
python如何统计序列中元素
2020/07/31 Python
基于pip install django失败时的解决方法
2018/06/12 Python
python执行CMD指令,并获取返回的方法
2018/12/19 Python
Python实现对adb命令封装
2020/03/06 Python
Python基于模块Paramiko实现SSHv2协议
2020/04/28 Python
python批量修改交换机密码的示例
2020/09/22 Python
Sentry错误日志监控使用方法解析
2020/11/12 Python
美国豪华的多品牌精品店:The Webster
2019/07/31 全球购物
Lookfantastic阿联酋官网:英国知名美妆护肤购物网站
2020/05/26 全球购物
软件工程师岗位职责
2013/11/16 职场文书
2014政府领导班子对照检查材料思想汇报(3篇)
2014/09/26 职场文书
小学优秀学生评语
2014/12/29 职场文书
博士论文答辩开场白
2015/06/01 职场文书
成事在人观后感
2015/06/16 职场文书
Python面向对象之内置函数相关知识总结
2021/06/24 Python
MySQL定时备份数据库(全库备份)的实现
2021/09/25 MySQL
Spring this调用当前类方法无法拦截的示例代码
2022/03/20 Java/Android