微信小程序用 canvas 实现手写签名弹框(全网最最最详细!!)

文章目录

  • 一、签字面板效果图
  • 二、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会遇到的问题及如何解决

🌸微信小程序给出的解决方案:
在这里插入图片描述



来源:春哥技术博客,欢迎分享,转载请注明出处。(欢迎加春哥团队客服微信号:taike668)

本文地址:https://www.cgtblog.com/cgymlt/11162.html
上一篇:在微信小程序中如何支持使用流模式(str      下一篇:关机恶搞小程序