一、簽字面板效果圖


二、WXML文件
??點(diǎn)擊彈出手寫簽名面板事件
<van-button type="default" bindtap="handWrittenSign">點(diǎn)擊彈出手寫簽名彈框</van-button>
??手寫簽名面板 Popup 彈出層(vant)
<van-popup show="{{ showWritten }}" position="bottom" custom-class="writtenArea" bind:close="writtenSignClose">
<view class="agree-area">
<text>請(qǐng)簽字以確認(rèn)同意用戶服務(wù)協(xié)議</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">確認(rèn)</van-button>
</view>
</van-popup>
三、JS文件
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
showWritten: false, //展示手寫簽名彈框
startX: undefined, // 線條的坐標(biāo)點(diǎn)
startY: undefined,
userSignatureId: undefined, // 簽名圖片id
screenWidth: undefined, // 屏幕寬
screenHeight: undefined, // 屏幕高
},
/**
* 事件
*/
// 點(diǎn)擊彈出手寫簽名彈框
handWrittenSign() {
this.setData({ showWritten: true });
this.initCanvas();
},
// 點(diǎn)擊蒙層關(guān)閉彈框
writtenSignClose() {
this.setData({ showWritten: false });
this.resetWrite();
},
// 初始化畫布
initCanvas() {
const context = wx.createCanvasContext('myCanvas', this);
context.setStrokeStyle('#000'); // 設(shè)置線條樣式
context.setLineWidth(3); // 線條粗細(xì)
context.setLineCap('round'); // 設(shè)置線條端點(diǎn)樣式
context.setLineJoin('round'); // 設(shè)置線條交點(diǎn)樣式(拐角)
context.beginPath(); // 開始新的繪制路徑
context.clearRect(0, 0, this.data.startX, this.data.startY); // 清除畫布上的內(nèi)容
context.draw(); // 繪制到canvas上
},
// 手指觸摸動(dòng)作開始
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,
})
},
// 手指觸摸后移動(dòng)
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,
})
},
// 手指觸摸動(dòng)作結(jié)束
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); // 繪制一個(gè)矩形清除畫布內(nèi)容
context.setLineWidth(3); // 線條粗細(xì)
// 繪制提示文字(根據(jù)需求可要可不要)
context.setFontSize(14);
context.setFillStyle('#999999');
context.setTextAlign('center');
context.fillText('請(qǐng)?jiān)诖藚^(qū)域簽名', 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();
},
// 確認(rèn)提交
confirmWrite() {
this.setData({showWritten: false}); // 關(guān)閉手寫面板
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)
})
}
});
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面顯示
*/
onShow() {
// 獲取屏幕的寬高 可結(jié)合畫布在父元素的百分比獲取實(shí)際寬高度;若畫布為固定值,以上所用寬高度可不用在此獲取,直接寫死即可。
const systemInfo = wx.getSystemInfoSync();
this.setData({
screenWidth: systemInfo.screenWidth,
screenHeight: systemInfo.screenHeight
})
},
})
??最后可以使用 canvas
組件的 toTempFilePath
方法將 canvas
畫布內(nèi)容保存為臨時(shí)文件路徑,然后將該路徑傳遞給后端即可。
四、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);
,我這里是直接在函數(shù)內(nèi)部定義方法,內(nèi)部使用。也可全局定義,使用wx.createCanvasContext
獲取繪圖上下文 context全局使用,如下:文章來源:http://www.zghlxwxcb.cn/news/detail-753774.html
Page({
data: {
canvasContext: null // canvas上下文對(duì)象
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面初次渲染完成
*/
onReady() {
this.data.canvasContext = wx.createCanvasContext('myCanvas', this);
},
// ...
})
六、IOS會(huì)遇到的問題及如何解決
??微信小程序給出的解決方案:文章來源地址http://www.zghlxwxcb.cn/news/detail-753774.html
到了這里,關(guān)于微信小程序用 canvas 實(shí)現(xiàn)手寫簽名彈框(全網(wǎng)最最最詳細(xì)?。。┑奈恼戮徒榻B完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!