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

本文实例为大家分享了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>

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

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

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

(0)

相关推荐

  • vue 使用 canvas 实现手写电子签名

    功能 兼容 PC 和 Mobile: 画布自适应屏幕大小变化(窗口缩放.屏幕旋转时画布无需重置,自动校正坐标偏移): 自定义画布尺寸(导出图尺寸),画笔粗细.颜色,画布背景色: 支持裁剪 (针对需求:有的签字需要裁剪掉四周空白). 导出图片格式为 base64 : 示例demo 安装 npm install vue-esign --save 使用 main.js 中引入 import vueEsign from 'vue-esign' Vue.use(vueEsign) 页面中使用 必须设置 r

  • 基于canvas实现手写签名(vue)

    最近一直在研究canvas的东西,正好之前对手写签名这块有点兴趣.就自己基于vue写了一个简易的手写签名demo. 其中原理比较简单,先生成一个canvas画布,并对canvas进行touchstart和touchmove事件进行监听.当监听touchstart事件被触发时,我们开始触发canvas里的beginPath事件并且设置moveTo原始点.当监听touchmove事件则去不断去触发lineTo事件,最后stroke(). demo里还有清除签名和保存签名的功能,分别对应了clearR

  • vue移动端使用canvas签名的实现

    效果 canvas画板移动端 .gif 需求   在一些项目业务中,经常会使用到画板,让用户自己去写/画一些东西做标示,比如说在线签电子合约.签名等,如果不用插件,那么如何使用h5的canvas画布来实现这一需求呢? [本篇只讨论移动端,PC端请看上篇] 分析   很明显,我们需要一个canvas,关于canvas的一些基本操作可以在w3school或者别的一些平台上熟悉一下,其实本例也是基础操作.本案例在vue中完成.(脱离vue也一样.) 首先,需要一个canvas画布 其次,考虑逻辑 把逻

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

    本文实例为大家分享了vue+canvas实现移动端手写签名的具体代码,供大家参考,具体内容如下 <template> <div class="sign"> <div class="header"> <i class="el-icon-arrow-left backImg" @click="goBack"></i> <span class="title&

  • vue使用canvas实现移动端手写签名

    基于vue使用canvas实现移动端手写签名! 之前自己开发有这么一个需求,需要实现手写签名,然后以图片的形式保存生成图片的base64数据流 .自己在网上找了一堆,都不是很完美.然后参考网上的加自己的优化和修改做了一版.希望有需要的朋友可以拿来直接用. HTML部分: <template> <div class="hello" > <div>请输入您的签名7:</div> <canvas id="canvas"

  • Vue使用sign-canvas实现在线手写签名的实例

    目录 更新日志 安装 全局方式 局部方式 效果图: sign-canvas 一个基于 canvas 开发,封装于 Vue 组件的通用手写签名板(电子签名板),支持 pc 端和移动端. 更新日志 v1.1.4 功能更新:增加全屏手写方案,可以通过 options.isFullScreen,和 options.isFullCover 属性控制,全屏模式下 canvasWidth 和 canvasHeight 属性设置无效,感谢网友 AFelicity”的建议与反馈. v1.1.3 功能更新:增加高倍

  • 使用vue实现手写签名功能

     个人实现截图: 安装: npm install vue-esign --save 使用: 1.在main.js中引入 import vueEsign from 'vue-esign' Vue.use(vueEsign) 2.在页面中引用 <vue-esign ref="esign" :width="800" :height="300" :isCrop="isCrop" :lineWidth="lineWidt

  • 微信小程序canvas实现手写签名

    本文实例为大家分享了微信小程序canvas实现手写签名的具体代码,供大家参考,具体内容如下 很多时候,程序中需要用到签名的功能,附上源码(微信小程序) .wxml <view class="canvasBox">       <view class="canvasTitle">请签名:</view>       <view class="canvasContent">         <vie

  • Android实现手写签名

    本文实例为大家分享了Android手写签名的实现方法,产品要求用户可以在app上签协议..所以得弄个手写签名版,参考了一些资料自己写了个PaintView去继承View,实现签名功能. package com.****.*****.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color;

  • Android实现屏幕手写签名

    Android屏幕手写签名的原理就是把手机屏幕当作画板,把用户手指当作画笔,手指在屏幕上在屏幕上划来划去,屏幕就会显示手指的移动轨迹,就像画笔在画板上写字一样.实现手写签名需要结合绘图的路径工具Path,在有按下动作时调用Path对象的moveTo方法,将路径起始点移动到触摸点:在有移动操作时调用Path对象的quadTo方法,将记录本次触摸点与上次触摸点之间的路径:在有移动操作与提起动作时调用Canvas对象的drawPath方法,将本次触摸绘制在画布上. layout/activity_si

  • android实现手写签名功能

    本文实例为大家分享了android手写签名展示的具体代码,供大家参考,具体内容如下 代码简单,就不发demo了,直接贴代码 package com.xx; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android

  • Android 自定义View手写签名并保存图片功能

    GIF压缩有问题,运行很顺滑!!! 1.自定义View--支持设置画笔颜色,画笔宽度,画板颜色,清除画板,检查是否有签名,保存画板图片(复制粘贴可直接使用) /** * Created by YyyyQ on 2020/3/5. * 电子签名 */ public class SignatureView extends View { private Context context; //X轴起点 private float x; //Y轴起点 private float y; //画笔 priva

随机推荐