微信小程序做电子签名功能
文章目录
最近需求要做就记录一下。
人狠话不多,直接上功能:
直接搂代码吧,复制过去就可以用,有其他需求自己改吧改吧。
signature.wxml
<!-- 电子签名页面 -->
<custom-navbar
title="电子签名"
show-home="{{false}}"
/>
<view class="signature-page">
<!-- 顶部操作栏 -->
<view class="action-bar">
<t-button theme="primary" icon="refresh" bind:tap="handleClear">重写</t-button>
<t-button theme="primary" icon="rollback" bind:tap="handleUndo">撤销</t-button>
<t-button theme="primary" icon="check" bind:tap="handleSubmit">提交</t-button>
</view>
<!-- 签名区域 -->
<view class="signature-area-large">
<canvas
type="2d"
id="signatureCanvas"
class="signature-canvas-large"
disable-scroll="{{true}}"
bindtouchstart="handleTouchStart"
bindtouchmove="handleTouchMove"
bindtouchend="handleTouchEnd"
></canvas>
</view>
<!-- 提示文本 -->
<view class="signature-tips">
请在上方区域书写您的签名
</view>
</view>
注意:我是用的tdesign这个UI,所以是t-button
signature.wxss
/* 页面容器 */
.signature-page {
width: 100vw;
height: calc(100vh - 44rpx);
background-color: #f6f6f6;
display: flex;
flex-direction: column;
padding: 16rpx;
box-sizing: border-box;
}
/* 顶部操作栏 */
.action-bar {
display: flex;
justify-content: flex-end;
gap: 16rpx;
margin-bottom: 20rpx;
padding: 0 10rpx;
}
/* 自定义按钮样式 */
.action-bar .t-button {
min-width: auto;
padding: 0 16rpx;
font-size: 18rpx !important;
height: 35rpx !important;
line-height: 35rpx !important;
}
/* 按钮图标样式 */
.action-bar .t-icon,
.action-bar .t-button__icon,
.action-bar .t-button .t-icon {
font-size: 20rpx !important;
}
/* 签名区域-大尺寸 */
.signature-area-large {
flex: 1;
background-color: #ffffff;
border-radius: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
overflow: hidden;
position: relative;
margin: 0 auto;
width: 94vw;
height: 80vh;
}
/* 签名画布-大尺寸 */
.signature-canvas-large {
width: 100%;
height: 100%;
background-color: #ffffff;
}
/* 提示文本 */
.signature-tips {
text-align: center;
color: #999999;
font-size: 12px;
margin-top: 16rpx;
}
signature.js
Page({
data: {
ctx: null,
points: [], // 存储所有笔画
currentStroke: [], // 当前笔画
isDrawing: false,
},
/**
* 生命周期函数--监听页面加载
* 初始化画布设置
*/
onLoad() {
this.initCanvas();
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 初始化画布
* 设置画布大小、像素比例和画笔样式
*/
async initCanvas() {
const query = wx.createSelectorQuery();
query.select('#signatureCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
// 设置画布大小,使用新的API获取设备像素比
const dpr = wx.getWindowInfo().pixelRatio;
canvas.width = res[0].width * dpr;
canvas.height = res[0].height * dpr;
ctx.scale(dpr, dpr);
// 设置画笔样式
ctx.strokeStyle = '#000000';
ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
this.setData({ ctx });
});
},
/**
* 处理触摸开始事件
* 开始一个新的笔画,记录起始点
* @param {Object} e - 触摸事件对象
*/
handleTouchStart(e) {
const { x, y } = e.touches[0];
this.setData({
isDrawing: true,
currentStroke: [[x, y]]
});
this.data.ctx.beginPath();
this.data.ctx.moveTo(x, y);
},
/**
* 处理触摸移动事件
* 继续绘制当前笔画的路径
* @param {Object} e - 触摸事件对象
*/
handleTouchMove(e) {
if (!this.data.isDrawing) return;
const { x, y } = e.touches[0];
this.data.currentStroke.push([x, y]);
this.data.ctx.lineTo(x, y);
this.data.ctx.stroke();
},
/**
* 处理触摸结束事件
* 完成当前笔画,将其添加到笔画历史中
*/
handleTouchEnd() {
if (!this.data.isDrawing) return;
this.setData({
isDrawing: false,
points: [...this.data.points, this.data.currentStroke],
currentStroke: []
});
},
/**
* 清除画布内容
* 清空所有笔画记录和画布显示
*/
handleClear() {
const { ctx } = this.data;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
this.setData({ points: [] });
},
/**
* 撤销上一步操作
* 移除最后一笔,并重绘剩余的笔画
*/
handleUndo() {
if (this.data.points.length === 0) return;
const { ctx } = this.data;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// 移除最后一笔
const newPoints = this.data.points.slice(0, -1);
this.setData({ points: newPoints });
// 重绘所有笔画
newPoints.forEach(stroke => {
ctx.beginPath();
ctx.moveTo(stroke[0][0], stroke[0][1]);
stroke.forEach(([x, y]) => {
ctx.lineTo(x, y);
});
ctx.stroke();
});
},
/**
* 提交签名
* 将画布内容转换为图片并处理提交逻辑
* @returns {Promise<void>}
*/
async handleSubmit() {
if (this.data.points.length === 0) {
wx.showToast({
title: '请先签名',
icon: 'none'
});
return;
}
// todo: 这里根据具体业务写吧,我这只是举个例子
try {
// 将画布内容转换为图片
const tempFilePath = await new Promise((resolve, reject) => {
wx.canvasToTempFilePath({
canvas: this.data.ctx.canvas,
success: res => resolve(res.tempFilePath),
fail: reject
});
});
// 这里可以处理签名图片,比如上传到服务器
console.log('签名图片路径:', tempFilePath);
wx.showToast({
title: '提交成功',
icon: 'success'
});
// 返回上一页
setTimeout(() => {
wx.navigateBack();
}, 1500);
} catch (error) {
console.error('提交签名失败:', error);
wx.showToast({
title: '提交失败',
icon: 'error'
});
}
}
});
注意:handleSubmit 提交的逻辑根据具体的业务写
signature.json
{
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button"
},
"disableScroll": true,
"pageOrientation": "landscape"
}
注意:我是用的tdesign这个UI
"pageOrientation": "landscape"
这个是设置横屏
就是用canvas画,小程序里这种需求一般都是用canvas
收工,有需要copy去吧,哈哈哈哈哈哈哈哈哈哈
原文地址:https://blog.csdn.net/weixin_43106777/article/details/144391534
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!