【签名】PC端签名和小程序端签名实现

前言:最近接到了这样一个需求,需要在pc端和小程序端实现手写签名,两者都可以基于canvas实现手写签名功能
一、PC端手写签名

javascript 复制代码
// 此功能是基于Vue2实现的
<el-form-item label="签字" prop="auditSignImg">
   <div style="position: relative; width: 300px; height: 200px;">
     <canvas id="mycanvas" @mousedown="mousedown"></canvas>
     <i class="el-icon-refresh resetsign" style="
         font-size: 30px;
         position: absolute;
         right: 0;
         bottom: 0;
       " @click="clearcanvas" title="重置签名"></i>
   </div>
 </el-form-item>
 mounted() {
 	this.$nextTick(() => this.createCanvas())
 },
 methods: {
	// 关于签名
    createCanvas() {
      // 获取canvas 实例
      var canvas = document.getElementById("mycanvas");
      // 设置宽高
      canvas.width = this.config.width;
      canvas.height = this.config.height;
      // 设置一个边框,方便咱们检查及运用
      canvas.style.border = "1px solid #ccc";
      // 创立上下文
      this.ctx = canvas.getContext("2d");
      // 设置填充背景色
      this.ctx.fillStyle = "#fff";
      // 制作填充矩形
      this.ctx.fillRect(
        0, // x 轴开端制作方位
        0, // y 轴开端制作方位
        this.config.width, // 宽度
        this.config.height // 高度
      );
    },
    mousedown(e) {
      // 初始化
      // 获取偏移量及坐标
      const {
        offsetX,
        offsetY,
        pageX,
        pageY
      } = e;
      // 修正前次的偏移量及坐标
      this.client.offsetX = offsetX;
      this.client.offsetY = offsetY;
      this.client.endX = pageX;
      this.client.endY = pageY;
      // 铲除以上一次 beginPath 之后的一切途径,进行制作
      this.ctx.beginPath();
      // 依据装备文件设置进行相应装备
      this.ctx.lineWidth = this.config.lineWidth;
      this.ctx.strokeStyle = this.config.strokeStyle;
      this.ctx.lineCap = this.config.lineCap;
      this.ctx.lineJoin = this.config.lineJoin;
      // 设置画线开端点位
      this.ctx.moveTo(this.client.offsetX, this.client.offsetY);
      this.ctx.stroke();
      window.addEventListener("mousemove", this.mousemove);
    },
    mousemove(e) {
      // 获取当时坐标点位
      const {
        offsetX,
        offsetY
      } = e;
      // 依据坐标点位移动增加线条
      let h = document.getElementById("mycanvas").getBoundingClientRect().top;
      let w = document.getElementById("mycanvas").getBoundingClientRect().left;
      this.ctx.lineTo(e.clientX - w, e.clientY - h);
      // 制作
      this.ctx.stroke();
      window.addEventListener("mouseup", this.mouseup);
    },
    mouseup() {
      this.ctx.closePath();
      // 移除鼠标移动或手势移动监听器
      window.removeEventListener("mousemove", this.mousemove);
    },
    clearcanvas() {
      // 清空画布
      this.ctx.clearRect(0, 0, this.config.width, this.config.height);
      // 清空签名url
      this.rejectForm.auditSignImg = '';
    },
 }

二、小程序端手写签名

javascript 复制代码
// 此功能是基于uniapp+Vue3实现的
// SignCanvas.vue
<!-- 签名 -->
<template>
	<view class="canvas-signature">
		<canvas id="myCanvas" canvas-id="myCanvas" :style="{width: cWidth + 'px', height: cHeight + 'px', boxShadow: '-2rpx 2rpx 2rpx 0 rgba(0,0,0,0.1), 2rpx -2rpx 2rpx 0 rgba(0,0,0,0.1)',
      borderRadius: '8rpx 8rpx 8rpx 8rpx'}" @touchstart.stop="touchStart" @touchmove.stop="touchMove" @touchend.stop="touchEnd">
    </canvas>
		<view class="btn-wrap">
			<view class="btn clean base-btn" @click="clear">
				<text>重写</text>
			</view>
			<view class="btn save base-btn" @click="save">
				<text>{{btnText}}</text>
			</view>
		</view>
	</view>
</template>
<script>
import { uploadFile } from '@/utils/file.js'
import { $showToast } from '@/utils/index.js'

let ctx = null
export default {
  props:{
    cHeight: {
      type: Number,
      default: 200
    },
    strokeStyle: {
      type: String,
      default: '#000'
    },
    lineWidth: {
      type: Number,
      default: 3
    },
    btnText: {
      type: String,
      default: '保存'
    },
    pageType: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      cWidth: 375,
      touchStartX: 0, // 手指触摸开始x坐标
      touchStartY: 0, // 手指触摸开始y坐标
      moveX: 0, // 移动x坐标
      moveY: 0, // 移动y坐标
      hasContent: false // 是否已签名
    }
  },
  mounted() {
    const res = uni.getWindowInfo()
    this.cWidth = res.screenWidth * 0.9
    ctx = uni.createCanvasContext('myCanvas', this)
    ctx.lineWidth = this.lineWidth
    ctx.strokeStyle = this.strokeStyle
    ctx.lineCap = 'round'
  },
  methods: {
    touchStart(e) {
      const {touches} = e			
      this.touchStartX = touches[0].x
      this.touchStartY = touches[0].y
      // 每次触摸开始,开启新的路径
      ctx.beginPath()
    },
    touchMove(e) {
      const {touches} = e
      this.moveX = touches[0].x
      this.moveY = touches[0].y
      // 两点画一笔
      ctx.moveTo(this.touchStartX, this.touchStartY)
      ctx.lineTo(this.moveX,this.moveY)
      ctx.stroke()
      ctx.draw(true) // 将上一次的终点作为下一次绘制的起点
      this.touchStartX = this.moveX
      this.touchStartY = this.moveY
      this.hasContent = true
    },
    touchEnd(e) {},
    // 保存
    save() {
      if (!this.hasContent) {
        $showToast('请先签名')
        return
      }
      uni.canvasToTempFilePath({
        canvasId: 'myCanvas',
        success: (res) => {
          uploadFile(res?.tempFilePath).then(result => {
            this.$emit('handleSingature', result?.fileName)
          })
        },
        fail: (error) => {
          console.log('回调错误', error);
        }
      }, this)
    },
    // 重写
    clear() {
      this.hasContent = false
      ctx.clearRect(0, 0, this.cWidth, this.cHeight)
      ctx.draw(true)
    }
  }
}
</script>

<style lang="scss" scoped>
.canvas-signature {
  background: #FFFFFF;
  .btn-wrap {
    display: flex;
    justify-content: space-around;
    background: #fff;
    padding: 20rpx 0;
    border-top: 1rpx solid #f5f5f5;
    .btn,&.clean {
      width: 40%;
      height: 104rpx;
      line-height: 104rpx;
      border-radius: 20rpx 20rpx 20rpx 20rpx;
      font-size: 36rpx;
    }
    .btn {
      padding: 0 14rpx;
      color: #ffffff;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #0FAD70;
      &.clean {
        margin-right: 20rpx;
        background-color: #ffffff;
        border: 2rpx solid #C6C6C8;
        color: #333333;
      }
    }
  }
}
</style>

// 父组件引用SignCanvas.vue
<my-canvas cHeight="460" @handleSingature="handleSingature"></my-canvas>
handleSingature(fileName) {
	// 手写签名转成的文件名
	console.log(fileName)
}
相关推荐
qq_174482857514 小时前
基于微信小程序的小动物救助领养平台
微信小程序·小程序
邓草18 小时前
apache、iis规则屏蔽拦截ClaudeBot等蜘蛛爬虫抓取网页
apache·dubbo
榕树子18 小时前
[java] 什么是 Apache Felix
java·开发语言·apache
寂然如故18 小时前
Apache Spark
大数据·spark·apache
wcy011220 小时前
微信小程序+Vant-自定义选择器组件(单选带筛选
微信小程序·小程序
Fresh-eyes21 小时前
iphone小程序设置burpsuite代理抓包
运维·服务器·小程序
paterWang21 小时前
小程序-基于java+SpringBoot+Vue的铁路订票平台小程序设计与实现
java·spring boot·小程序
流着口水看上帝1 天前
一文掌握如何用python开发小程序
python·小程序
非著名程序员1 天前
15分钟做完一个小程序,腾讯这个工具有点东西
小程序
1登峰造极1 天前
uniapp中uni-popup在小程序中滚动穿透问题
小程序·uni-app