业务需求:在微信小程序内的商家入驻协议页面的下面设置一个空白区域,可以让用户在手机屏幕上进行手指滑动,从而实现手写签名的功能。
设计思路:
1 创建一个canvas对象
2 监听用户手指触摸事件bindtouchstart=”start”
3 开始触摸时保存坐标x,y
4 触摸移动时bindtouchmove=”move” 执行绘制操作ctx.stroke
5 保存图片通过wx.canvasToTempFilePath把临时路径返回出去用户上传接口使用
全部代码:
WXML
<view>
<canvas
class="c-autograph"
style="width:{{canvasW}}px;height:{{canvasH}}px;"
canvas-id="autograph"
bindtouchcancel="cancel"
bindtouchmove="move"
bindtouchstart="start"
bindtouchend="end"
bindlongtap="longtap"
disable-scroll="true"
binderror="error"
></canvas>
</view>
JS
/*
* @Author: liuxiaofan
* @Description: v2.0.0
* @Date: 2020-03-10 15:56:34
* @LastEditors: liuxiaofan
* @LastEditTime: 2020-04-20 15:40:55
*/
// 采坑: 如果html标签里面写了 type="2d",会导致真机空白
var ctx = null; //canvas实例
var touchs = [];
Component({
properties: {
},
data: {
canvasW: 140,
canvasH: 56,
lineColor: '#333', // 笔划的颜色
LineWidth: 3, //笔划粗细
count: 0 //画了几笔
},
ready() {
this.autoWidth()
this.init()
},
methods: {
autoWidth() {
const dpr = wx.getSystemInfoSync().pixelRatio // 获取设备的屏幕分辨率是2x还是3x
let canvasW, canvasH;
if (dpr >= 2) {
canvasW = this.data.canvasW * 2
canvasH = this.data.canvasH * 2
}
if (dpr >= 3) {
canvasW = this.data.canvasW * 2.21
canvasH = this.data.canvasH * 2.21
}
// 最近小高度100
if (canvasH < 100) {
canvasH = 100
}
if (canvasW < 280) {
canvasW = 280
}
this.setData({
canvasW,
canvasH,
})
},
init: function (options) {
ctx = wx.createCanvasContext('autograph', this); // 如果是组件的形式,第2个参数要写this
ctx.setStrokeStyle(this.data.lineColor);
ctx.setLineWidth(this.data.LineWidth);
ctx.setLineCap('round'); // 笔触形态
ctx.setLineJoin('round'); // 交叉点形态
},
// 画布的触摸移动开始手势响应
start: function (event) {
// console.log("触摸开始" + event.changedTouches[0].x);
// console.log("触摸开始" + event.changedTouches[0].y);
//获取触摸开始的 x,y
let point = { x: event.changedTouches[0].x, y: event.changedTouches[0].y }
touchs.push(point);
},
// 画布的触摸移动手势响应
move: function (e) {
let point = { x: e.touches[0].x, y: e.touches[0].y }
touchs.push(point);
if (touchs.length >= 2) {
this.draw(touchs);
}
},
// 画布的触摸移动结束手势响应
end: function (e) {
this.setData({
count: this.data.count + 1
})
// console.info("触摸结束" + this.data.count);
//清空轨迹数组
for (let i = 0; i < touchs.length; i++) {
touchs.pop();
}
},
// 画布的长按手势响应
longtap: function (e) {
// console.log("长按手势" + e);
},
cancel() { },
error: function (e) {
// console.log("画布触摸错误" + e);
},
//绘制
draw: function (touchs) {
let point1 = touchs[0];
let point2 = touchs[1];
// console.info(point1, point2)
touchs.shift();
ctx.moveTo(point1.x, point1.y);
ctx.lineTo(point2.x, point2.y);
ctx.stroke();
ctx.draw(true);
},
//清除操作
clearClick: function () {
//清除画布
ctx.clearRect(0, 0, 750, 700);
ctx.draw(true);
this.setData({
count: 0
})
},
//保存图片
saveClick: function (callback) {
if (this.data.count < 3) {
wx.showModal({
title: '提示',
content: '签名不符合规范,请重新签名',
showCancel: false
})
} else {
wx.canvasToTempFilePath({
canvasId: 'autograph',
fileType: 'jpg',
destWidth: 800,
destHeight: 500,
success: function (res) {
callback && callback(res.tempFilePath) //把图片路径回调出去
},
fail(res) {
console.info('保存失败', res)
}
}, this)
}
}
}
})
在父组件内的使用方式
this.selectComponent("#autograph").saveClick(function (tempFilePath) {
that.creatMerchant(tempFilePath)
})