文章目录
- 一、签字面板效果图
- 二、WXML文件
- 三、JS文件
- 四、WXSS文件
- 五、小Tips ~
- 六、IOS会遇到的问题及如何解决
一、签字面板效果图


二、WXML文件
🌸点击弹出手写签名面板事件
<van-button type="default" bindtap="handWrittenSign">点击弹出手写签名弹框</van-button>
🌸手写签名面板 Popup 弹出层(vant)
<van-popup show="{{ showWritten }}" position="bottom" custom-class="writtenArea" bind:close="writtenSignClose"> <view class="agree-area"> <text>请签字以确认同意用户服务协议</text> </view> <canvas type="3d" canvas-id="myCanvas" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd" class="canvas-area"></canvas> <view class="written-btn-area"> <van-button type="default" custom-class="write" bindtap="resetWrite" size="small">重置</van-button> <van-button plain type="info" custom-class="write" bindtap="cancelWrite" size="small">取消</van-button> <van-button type="info" custom-class="write" bindtap="confirmWrite" size="small">确认</van-button> </view></van-popup>
三、JS文件
Page({ /** * 页面的初始数据 */ data: { showWritten: false, //展示手写签名弹框 startX: undefined, // 线条的坐标点 startY: undefined, userSignatureId: undefined, // 签名图片id screenWidth: undefined, // 屏幕宽 screenHeight: undefined, // 屏幕高 }, /** * 事件 */ // 点击弹出手写签名弹框 handWrittenSign() { this.setData({ showWritten: true }); this.initCanvas(); }, // 点击蒙层关闭弹框 writtenSignClose() { this.setData({ showWritten: false }); this.resetWrite(); }, // 初始化画布 initCanvas() { const context = wx.createCanvasContext('myCanvas', this); context.setStrokeStyle('#000'); // 设置线条样式 context.setLineWidth(3); // 线条粗细 context.setLineCap('round'); // 设置线条端点样式 context.setLineJoin('round'); // 设置线条交点样式(拐角) context.beginPath(); // 开始新的绘制路径 context.clearRect(0, 0, this.data.startX, this.data.startY); // 清除画布上的内容 context.draw(); // 绘制到canvas上 }, // 手指触摸动作开始 onTouchStart(e) { const context = wx.createCanvasContext('myCanvas', this); context.setStrokeStyle('#000000'); context.setLineWidth(3); this.setData({ 'startX': e.touches[0].x, 'startY': e.touches[0].y, }) }, // 手指触摸后移动 onTouchMove(e) { const context = wx.createCanvasContext('myCanvas', this); context.moveTo(this.data.startX, this.data.startY); context.lineTo(e.touches[0].x, e.touches[0].y); context.stroke(); context.draw(true); this.setData({ 'startX': e.touches[0].x, 'startY': e.touches[0].y, }) }, // 手指触摸动作结束 onTouchEnd() { const context = wx.createCanvasContext('myCanvas', this); context.closePath(); context.draw(true); }, // 重置签名 resetWrite() { const context = wx.createCanvasContext('myCanvas', this); let { screenWidth, screenHeight } = this.data; // 清空画布 context.clearRect(0, 0, screenWidth, screenHeight); context.beginPath(); // 绘制白色背景 context.setFillStyle('#ffffff'); // 填充色 白色 context.fillRect(0, 0, screenWidth, screenHeight); // 绘制一个矩形清除画布内容 context.setLineWidth(3); // 线条粗细 // 绘制提示文字(根据需求可要可不要) context.setFontSize(14); context.setFillStyle('#999999'); context.setTextAlign('center'); context.fillText('请在此区域签名', this.data.startX / 2, this.data.startY / 2); // 绘制到canvas上 context.draw(); }, // 取消签名 cancelWrite() { this.setData({ showWritten: false }) const context = wx.createCanvasContext('myCanvas', this); let { screenWidth, screenHeight } = this.data; // 清空画布 context.clearRect(0, 0, screenWidth, screenHeight); context.beginPath(); context.setFillStyle('#ffffff'); context.fillRect(0, 0, screenWidth, screenHeight); context.setLineWidth(3); // 绘制到canvas上 context.draw(); }, // 确认提交 confirmWrite() { this.setData({showWritten: false}); // 关闭手写面板 wx.canvasToTempFilePath({ canvasId: 'myCanvas', success: function(res) { const tempFilePath = res.tempFilePath; // 取图片文件路径 // 将 tempFilePath 传递给后端接口 uploadFile({fileType: 'image', tempFilePath: tempFilePath}) .then(file => { // 由于签名面板在表单中,提交表单需要传签名文件id,在这里赋值 that.setData({ userSignatureId: file.id }) }) .catch(err => { console.error(err) }) } }); }, /** * 生命周期函数--监听页面显示 */ onShow() { // 获取屏幕的宽高 可结合画布在父元素的百分比获取实际宽高度;若画布为固定值,以上所用宽高度可不用在此获取,直接写死即可。 const systemInfo = wx.getSystemInfoSync(); this.setData({ screenWidth: systemInfo.screenWidth, screenHeight: systemInfo.screenHeight }) },})
🌸最后可以使用 canvas
组件的 toTempFilePath
方法将 canvas
画布内容保存为临时文件路径,然后将该路径传递给后端即可。
四、WXSS文件
.writtenArea { height: 60%; display: flex; justify-content: space-between; align-items: center; flex-direction: column;}.canvas-area { width: 90%; flex: 1; border: 1px solid #ccc;}.write { width: 180rpx;}.written-btn-area { width: 100%; display: flex; justify-content: space-between; padding: 0 40rpx; margin-top: 20rpx;}.agree-area { width: 90%; margin: 20rpx 0; text-align: left; font-size: 36rpx; font-weight: 700;}
五、小Tips ~
💡 文中触摸板的方法中多次获取canvas
的上下文,即const context = wx.createCanvasContext('myCanvas', this);
,我这里是直接在函数内部定义方法,内部使用。也可全局定义,使用wx.createCanvasContext
获取绘图上下文 context全局使用,如下:
Page({ data: { canvasContext: null // canvas上下文对象 }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { this.data.canvasContext = wx.createCanvasContext('myCanvas', this); }, // ...})
六、IOS会遇到的问题及如何解决
🌸微信小程序给出的解决方案: