微信小程序画布canvas(新版)实现签名功能

wxml文件:

 <!-- 签名画布 -->
   <canvas class="canvas" id="signature-board" disable-scroll="true" bindtouchstart="canvasStart"
     bindtouchmove="canvasMove" bindtouchend="canvasEnd" touchcancel="canvasEnd" type="2d">
   </canvas>

新版使用id获取canvas组件即可,旧版需要使用canvas-id。

wxss文件:

/* pages/signature/signature.wxss */
.container {
  padding: 20rpx;
  height: 100vh;
  width: 100vw;
  overflow: hidden; 
  display: flex;
  align-items:  center;
  /* background: radial-gradient(#fff, #000); */
  background-repeat: no-repeat;
  background-size: cover;
}
.block {
  height: calc(calc(100vw - 60rpx - 40rpx) / 2);
  /* max-height: 100%; */
  width: 100%;
  border-radius: 5rpx;
  overflow: hidden;
  display: flex;
  align-items:  center;
  background: rgba(255,255,255,.5);
  box-shadow: 0 0 30rpx 0 rgba(0,0,0,.3);
}
.drawarea {
  flex-grow: 2;
  height: 100%;
  width: 100%;
  position: relative;
}
.sign-hint {
  position: absolute;
  top: 0;
  left: 10rpx;
  right: 0;
  bottom: 0;
  z-index: 0;
  margin: auto;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  font-size: 40rpx;
  letter-spacing: .2em;
  color: rgba(0,0,0,.2);
  word-break: keep-all;
  white-space: pre-line;
}
.canvas {
  flex-grow: 2;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
} 
.button-box {
  flex-grow: 0;
  flex-shrink: 0;
  height: 100%;
  width: 40rpx;
  padding: 30rpx 10rpx 30rpx 0;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.cu-btn {
  width: 100%!important;
  height: 50%!important;
  padding: 0 2.5rpx 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15rpx;
}
.cu-btn:first-of-type {
  margin: 0 0 30rpx 0;
}
.btn-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  writing-mode: vertical-rl;
  color: #fff;
  font-size: 14px;
}

json文件:

{
    "usingComponents": {},
    "pageOrientation": "landscape"
}

js文件:

const MAX_V = 1; // 最大书写速度
const MIN_V = 0; // 最小书写速度
const MAX_LINE_WIDTH = 16; // 最大笔画宽度
const MIN_LINE_WIDTH = 4; // 最小笔画宽度
const MAX_LINE_DIFF = .03; // 两点之间笔画宽度最大差异
let context = null; // canvas上下文
let lastPoint = null; // 包含上一点笔画信息的对象
Page({
  data: {
    drawn: false,
  },
  onShow: function (options) {
    this.canvasInit();
  },
  canvasInit: function () {
    wx.createSelectorQuery() 
    .select('#signature-board') // 在 WXML 中填入的 id
    .fields({ node: true, size: true })
    .exec((res) => {
      res[0].node.width = res[0].width;
      res[0].node.height = res[0].height;
        context = res[0].node.getContext("2d")
    })

  },
  canvasMove: function (e) {
    this.setData({
      drawn: true
    })
    let currPoint = {
      x: e.changedTouches[0].x, // X坐标
      y: e.changedTouches[0].y, // Y坐标
      t: new Date().getTime(), // 当前时间
      w: (MAX_LINE_WIDTH + MIN_LINE_WIDTH) / 2 /*默认宽度 */
    };
    if (lastPoint) {
      currPoint.w = this.calcLineWidth(currPoint); // 重新赋值宽度,覆盖默认值 
      context.beginPath();
      context.strokeStyle = '#000';
      context.lineCap = 'round';
      context.lineJoin = 'round';
      context.lineWidth = currPoint.w;
      context.moveTo(lastPoint.x, lastPoint.y);
      context.lineTo(currPoint.x, currPoint.y);
      context.stroke();
    }
    lastPoint = currPoint; // 结束前保存当前点为上一点
  },
  // 计算当前点的宽度,书写速度越快,笔画宽度越小,呈现出笔锋的感觉(笑)
  calcLineWidth: function (currPoint) {
    let consuming = currPoint.t - lastPoint.t; // 两点之间耗时
    if (!consuming) return lastPoint.w; // 如果当前点用时为0,返回上点的宽度。
    let maxWidth = Math.min(MAX_LINE_WIDTH, lastPoint.w * (1 + MAX_LINE_DIFF)); // 当前点的最大宽度
    let minWidth = Math.max(MIN_LINE_WIDTH, lastPoint.w * (1 - MAX_LINE_DIFF * 3)); // 当前点的最小宽度,变细时速度快所以宽度变化要稍快
    let distance = Math.sqrt(Math.pow(currPoint.x - lastPoint.x, 2) + Math.pow(currPoint.y - lastPoint.y, 2)); // 两点之间距离
    let speed = Math.max(Math.min(distance / consuming, MAX_V), MIN_V); /*当前点速度*/
    let lineWidth = Math.max(Math.min(MAX_LINE_WIDTH * (1 - speed / MAX_V), maxWidth), minWidth); /* 当前点宽度 */
    return lineWidth;
  },
  canvasEnd: function (e) {
    lastPoint = null; // 每笔画完清除缓存
  },
  canvasClear: function () {
    this.setData({
      drawn: false
    })
    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    // context.draw(false);
  },
  canvasOut: function () {
    wx.navigateBack({
      delta: 1,
    })
  },
  finish: function () {
    if (!this.data.drawn) {
      return;
    }
	//由于新版的canvas的wx.canvasToTempFilePath方法一直报错,只能通过以下方式来获取签名图片
    const res = context.canvas.toDataURL("image/png");
    const fsm = wx.getFileSystemManager();
    const FILE_BASE_NAME = "tmp_base64src_" + new Date().getTime();
    const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.png`;
    fsm.writeFile({
      filePath,
      data: res.replace(/^data:image\/\w+;base64,/, ""),
      encoding: "base64",
      success: () => {
          this.getOpenerEventChannel().emit('signature', filePath); //传签名图片的临时路径回上一页
          wx.navigateBack();
      },
      fail() {
        wx.showToast({ title: "生成签名失败", icon: "none" });
      },
    });
  },
})

签名效果:
在这里插入图片描述

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
是的,可以使用Canvas实现微信小程序签名功能。以下是实现步骤: 1. 在wxml文件中添加Canvas标签,设置宽高和id属性,如: ```html <canvas canvas-id="myCanvas" style="width: 100%; height: 100%;"></canvas> ``` 2. 在相应的js文件中获取Canvas对象,如: ```javascript const ctx = wx.createCanvasContext('myCanvas') ``` 3. 监听touch事件,获取坐标并在Canvas上绘制线条,如: ```javascript let startX = 0 let startY = 0 let moveX = 0 let moveY = 0 let drawing = false wx.createSelectorQuery().select('#myCanvas').fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node const ctx = canvas.getContext('2d') canvas.addEventListener('touchstart', (e) => { startX = e.touches[0].x startY = e.touches[0].y drawing = true }) canvas.addEventListener('touchmove', (e) => { if (!drawing) { return } moveX = e.touches[0].x moveY = e.touches[0].y ctx.beginPath() ctx.moveTo(startX, startY) ctx.lineTo(moveX, moveY) ctx.stroke() startX = moveX startY = moveY }) canvas.addEventListener('touchend', () => { drawing = false }) }) ``` 4. 在需要保存签名的地方调用Canvas对象的toTempFilePath方法,如: ```javascript wx.canvasToTempFilePath({ canvasId: 'myCanvas', success: (res) => { console.log(res.tempFilePath) } }) ``` 至此,签名功能实现了。需要注意的是,Canvas是一个像素级别的绘图工具,需要自己处理每一个像素点的绘制,所以在实现时需要注意性能和体验问题。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值