赞
踩
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" }); }, }); }, })
签名效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。