记录一下小程序的手写签名组件


前言

由于前一段时间的电子合同功能需要合同双方的签名,在此记录一下小程序前端的手写签名组件。


提示:以下是本篇文章正文内容,下面案例可供参考

一、.js文件的内容

// pages/component/signature/signature.js
var cxt = null;// 使用 wx.createContext 获取绘图上下文 cxt
var arrx = [];//所有点的X轴集合
var arry = [];//所有点的Y轴集合
var canvasw = 0;//画布的宽 
var canvash = 0;//画布的高
// var canvasTop=0;
// var canvasLeft=0;
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    can:Boolean,//用于显示隐藏canvas
  },
 
  /**
   * 组件的初始数据
   */
  data: {
    src:""
  },
 
  /**
   * 组件的方法列表
   */
  methods: {
    //显示隐藏组件
    back(){
        //子组件传递给父组件一个方法canvasDis,并传递一个参数src给父组件
      this.triggerEvent("canvasDis",{src:this.data.src})
    },
    //创建canvas上下文
    createdCanvas(){
      wx.showLoading({
        title: '加载中...',
        mask: true
      })
      // 使用 wx.createContext 获取绘图上下文 cxt
      //创建 canvas 的绘图上下文,因为这里是封装成组件,所有需要加this
      cxt = wx.createCanvasContext('canvas',this);
      cxt.beginPath();
      //封装成组件,所有需要in(this),如果不加无法创建画布
      var query = wx.createSelectorQuery().in(this).select('.handCenter');
      query.boundingClientRect(rect => {
        // canvasTop = rect.top;
        // canvasLeft = rect.left;
        canvasw = rect.width/2;
        canvash = rect.height/2;
        // var ratio = 2;
        // while (canvasw > 150){// 保证宽在150以内
        //   canvasw = Math.trunc(res.width / ratio)
        //   canvash = Math.trunc(res.height / ratio)
        //     ratio++;
        // }
        wx.hideLoading()
      }).exec();
    },
    //canvas发生错误时触发
    canvasIdErrorCallback(e){
      console.error(e.detail.errMsg)
    },
    //canvas触摸开始
    canvasStart(e){
      arrx.push(e.changedTouches[0].x);
      arry.push(e.changedTouches[0].y);
    },
    //canvas触摸过程中
    canvasMove(e){
      let len = arrx.length;
      cxt.moveTo(arrx[len - 1], arry[len - 1]);//把路径移动到画布中指定的点,第一个参数为x轴,第二个参数为y轴
      arrx.push(e.changedTouches[0].x);//手指移动过程中canvas的横坐标存入到全局数组变量arrx中
      arry.push(e.changedTouches[0].y);//手指移动过程中canvas的纵坐标存入到全局数组变量arry中
      cxt.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);//moveTo坐标到lineTo坐标的
      cxt.setLineWidth(4);//设置线条的宽度
      cxt.setLineCap('round');//设置结束时 点的样式
      cxt.stroke();//画线
      cxt.draw(true);//设置为true时,会保留上一次画出的图像,false则会清空(方式二设置为false,一为true)
    },
    getimg() {
      if (arrx.length == 0) {
        wx.showModal({
          title: '提示',
          content: '签名内容不能为空!',
          showCancel: false
        });
        return false;
      };
      wx.showLoading({
        title: '签名生成中..',
        mask:true
      })
      let that = this;
      wx.canvasToTempFilePath({
        canvasId: 'canvas',
        success: function (res) {
          that.setData({
            src: res.tempFilePath
          })
          wx.hideLoading();
//子组件传递给父组件一个方法canvasDis,并传递一个参数src给父组件
          that.triggerEvent("canvasDis",{src:res.tempFilePath})
        }
      },this)
    },
    cleardraw() {
      //清除画布
      arrx = [];
      arry = [];
      cxt.clearRect(0, 0, canvasw, canvash);
      cxt.draw();
      this.setData({src:''});
    },
    canvasEnd(e){}
  },
  ready(){
    this.createdCanvas()
  }
})

二、.json文件的内容

{
    "component": true,
    "usingComponents": {}
  }

三、.wxml文件的内容

<view class="wrapper">
	<view class="back" catchtap="back">返回</view>
	<view class="handBtn">
		<button catchtap="cleardraw" class="delBtn">清空</button>
		<button catchtap="getimg" class="subBtn">完成</button>
	</view>
	<view class="handCenter">
		<canvas class="canvas"
			id="canvas"
			canvas-id="canvas"
			disable-scroll="true"
			bindtouchstart="canvasStart"
			bindtouchmove="canvasMove"
			binderror="canvasIdErrorCallback"></canvas>
		<cover-image class='overImg' src="{{src}}" wx:if="{{src!=''}}"></cover-image>
	</view>
</view>

四、.wxss文件的内容

.wrapper{
    position: fixed;
    top:0;
    bottom: 0;
    right: 0;
    left: 0;
    box-sizing: border-box;
    background-color: #fff;
    z-index: 99999;
  }
  .back{
    width: 160rpx;
    background: #008ef6;
    margin: 20rpx;
    padding: 10rpx 0;
    color:#fff;
    border-radius:16rpx;
    text-align: center;
  }
  .handCenter{
    box-sizing: border-box;
    width: 100%;
  }
  canvas {
    width:100%;
    height: 310rpx;
    margin:auto;
  }
  .overImg{
    width: 200rpx;
    height: 200rpx;
  }
  .handCenter {
    box-sizing: border-box;
  }
  .handBtn {
    height: 100rpx;
    display: flex;
    align-content: space-between;
    align-items: center;
    margin-top:40rpx;
  }
  .delBtn {
    width: 40%;
    color: #666;
  }
  .subBtn {
    width: 40%;
    background: #008ef6;
    color: #fff;
  }
  button{
    font-size: 28rpx;
  }

五、要引用的.wxml文件的内容

  <view class="cu-form-group">
    <view class="title text-cyan light">签名</view>
    <view class='cu-tag bg-cyan radius padding' bindtap='handlChangeCanvasShow'>
      点击设置
    </view>
  </view>
  <signature
      wx:if="{{can}}"
      backInfo="{{can}}"
      bindcanvasDis="handlChangeCanvasShow"
      >
  </signature>
  <image wx:if="{{src}}" src='{{src}}'
                     style="width: 100%;height: 310rpx;border:1px solid #ccc"></image>

六、要引用的.js文件的内容

data: {
    dataNow: moment().format('YYYY-MM-DD'),
    liveDate: moment().format('YYYY-MM-DD'),
    // leaveDate: moment().add(1,"months").format('YYYY-MM-DD'),
    leaseDuration: 1,//
    multiArray: [],
    multiIndex: [0, 0],
    roomTypeList:[],
    waterMode:1,//
    refundWay: false, //
    showRefundWay: false,
    priceLineList: [],
    newPriceLineList: [],
    can:false,
    src:"",
    imageSrc:"",
    imageBase64: ''
  },
//handlChangeCanvasShow自定义事件,子组件传递过来的方法和数据
  handlChangeCanvasShow(e){
    let that = this
    that.setData({
      can:(!this.data.can)
    })
    //显示隐藏canvas
    if (e.changedTouches == undefined && e.detail.src != '') {
      wx.getFileSystemManager().readFile({
        filePath: e.detail.src, //选择图片返回的相对路径
        encoding: 'base64', //编码格式
        success: res => { //成功的回调
          that.setData({
            imageBase64: res.data
          })
        }
      })
      that.setData({
        src:e.detail.src
      })
      //点击了确定就把图片直接保存并更新并重新加载页面
      wx.uploadFile({
        url: http.api.fileupload,
        filePath: e.detail.src,
        name: 'file',
        formData: {
          dir: 'jianxi_s_addSign',
        },
        success(res) {
          let data = JSON.parse(res.data)
          if (data.code == 0) {
            that.setData({
              imageSrc: data.url
            })
          } else {
            util.hideLoading()
          }
        },
        fail() {
          util.hideLoading()
        }
      })
    } else {
      let imageUrl = this.data.signUrl == "undefined" ? '' : this.data.signUrl;
      that.setData({
        src: imageUrl
      })
    }
  },

七、总结

这个是小程序的签名案例,可以参考。


版权声明:本文为weixin_44117635原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。