微信小程序电子签名实现
实现签名方法就是使用canvas
<canvas canvas-id="firstCanvas" id='firstCanvas' bindtouchstart="bindtouchstart" bindtouchmove="bindtouchmove"></canvas>
<!-- 旋装图片 -->
<canvas canvas-id="saveImg" id='saveImg'></canvas>
<view class="clear" hidden="{{!sureBtn}}" bindtap='clear'>重新签名</view>
<view class="save {{sureBtn?'sureBet':''}}" bindtap='export'>完成</view>
在canvas上绑定手指点击事件和移动事件:
上图是想要实现的效果,
有几个考虑的点:
- 1、签字区域和按钮都是横屏显示的,这个首先想到的使用微信小程序的方法直接在json文件设置"pageOrientation":"landscape",但效果是整个屏幕横屏,标题也横,效果不同。只能通过css方法旋转实现按钮横屏展示
- 2、签字区域有个占位符,签字的时候需要去除,首先想到的是用个view去占位,然后点击切换为canvas,但是个人觉的略显刻意,就用canvas来旋转实现,bindtouchstart时让文字为空,这样也多了一个设置默认文字的函数
- 3、生成图片,在使用wx.canvasToTempFilePath({})的时候发现生成的图片也是反着的,这里用了一个笨方法,添加一个canvas来单独处理图片旋转
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
context: null,
index: 0,
height: 0,
width: 0,
writeTips: '请清晰书写您的英文签名',
writeTipsTrue: true,
src:'',
sureBtn:false,
saveContext:null
},
/**记录开始点 */
bindtouchstart: function (e) {
let { writeTipsTrue } = this.data
if (writeTipsTrue) {
this.data.context.clearRect(0, 0, this.data.width, this.data.height);
this.setData({ writeTipsTrue: false, sureBtn:true })
}
this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)
},
/**记录移动点,刷新绘制 */
bindtouchmove: function (e) {
this.data.context.setLineWidth(2) // 设置线条宽度
this.data.context.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);
this.data.context.stroke();
this.data.context.draw(true);
this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
},
/**清空画布 */
clear () {
let context = this.data.context
this.setData({ writeTipsTrue: true, sureBtn:false })
context.clearRect(0, 0, this.data.width, this.data.height);
// this.data.saveContext.clearRect(0, 0, this.data.height, this.data.width);
context.save();
context.setTransform(1, 0, 0, 1, Math.ceil(this.data.width / 2), 155); // 旋转画布 默认文字区域
context.rotate(Math.PI / 2);
let str = this.data.writeTips;
context.setFontSize(24)
context.setFillStyle('#ADADB2');
context.fillText(str, 0, 0)
context.restore();
context.draw()
},
/**导出图片 */
export () {
const that = this;
let signImg;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: that.data.width,
height: that.data.height,
destWidth: that.data.width,
destHeight: that.data.height,
canvasId: 'firstCanvas',
success (res) {
console.log(res.tempFilePath)
signImg = res.tempFilePath
that.setData({ src1: signImg})
//下载图片
wx.getImageInfo({
src: signImg, // 签字画布生成的暂存地址
success (res) {
// canvas绘制图片需要下载图片或者getImageInfo
console.log(res,'res');
let rototalImg = res.path
that.setData({ src: rototalImg})
if (rototalImg) {
// 单独处理图片旋转
that.saveImg(rototalImg)
}
}
})
}
})
},
// drew img
saveImg (signImg){
if (!this.data.sureBtn){
app.toast(this, {
type: 'text',
text: '请清晰书写您的英文签名'
})
return
}
// 旋转图
let that = this
const context = wx.createCanvasContext('saveImg');
this.setData({saveContext:context})
context.translate(that.data.width / 2, that.data.height / 2)
context.setTransform(1, 0, 0, 1, 0, Math.ceil(that.data.height / 2) -20);
context.rotate(-Math.PI / 2)
// context.drawImage(signImg, -that.data.width / 2, -that.data.height / 2, that.data.width, that.data.height)
context.drawImage(signImg, 0, 0, that.data.width, that.data.height)
// context.fill()
//绘制图片 生成图片函数写在draw()的回调中,不然会出现还没有画图就生成图片的问题
context.draw(true,()=>{
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: that.data.height,
height: that.data.width,
destWidth: that.data.height,
destHeight: that.data.width,
canvasId: 'saveImg',
fileType: 'png',
success: function (res) {
var tempFilePath = res.tempFilePath;
console.log(tempFilePath);
that.setData({ src: tempFilePath })
// 生成图片 并返回上一页 赋值
let curPages = getCurrentPages();
var prevPage = curPages[curPages.length - 2]
prevPage.setData({
signImg: tempFilePath,
})
wx.navigateBack({
delta: 1
});
},
fail: function (res) {
console.log(res);
}
});
})
},
onLoad: function (options) {
},
onShow: function () {
// 进入页面渲染canvas
let query = wx.createSelectorQuery();
const that = this;
let context
query.select('#firstCanvas').boundingClientRect();
query.exec(function (rect) {
let width = rect[0].width;
let height = rect[0].height;
that.setData({
width,
height
});
const context = wx.createCanvasContext('firstCanvas')
that.setData({
context: context
})
context.save();
// context.translate(Math.ceil(width / 2) - 20,0)
context.setTransform(1, 0, 0, 1, Math.ceil(width / 2), 155);
context.rotate(Math.PI / 2);
let str = that.data.writeTips;
// context.fillText(str, Math.ceil((width - context.measureText(str).width) / 2), Math.ceil(height / 2) - 20)
context.setFontSize(24)
context.setFillStyle('#ADADB2');
// context.fillRect(0, 0, that.data.height, that.data.width);
context.fillText(str, 0, 0)
context.restore();
context.draw()
});
},
// 弹窗
onToast(){
app.toast(this, {
type: 'text',
text: '生成成功'
})
},
onShareAppMessage: (res) => { }
})
相关注释代码中都有,也么有优化,有好的方法,还希望大佬们多多指点