微信小程序Canvas实现手写签名
功能描述
点击按钮显示弹窗,弹窗主体为签名板,底部两个按钮为清除和保存。
清除按钮:清空签名板
保存按钮:保存签名为图片,并关闭弹窗
关键点分析
- Canvas实现手写签名部分:签名不一定具有连续性;判断是否签名;签名需要明显一些
- 微信小程序api实现保存为图片
- 因为是弹窗显示签名板,方便以后其他地方调用就封装为小程序组件使用
功能实现
1.signature组件wxml
<view class="signature-modal" hidden="{{hideModal}}">
<view class="modal-mask" bindtap="closeModal"></view>
<view class="modal-content-area">
<view class="modal-title">签名板</view>
<view class="modal-content">
<canvas canvas-id="signature" class="modal-canvas" disable-scroll="{{true}}" id="handWriting" bindtouchstart="scaleStart"
bindtouchmove="scaleMove" bindtouchend="scaleEnd" ></canvas>
<view class="modal-bottom">
<view class="modal-btn modal-clear" bindtap="clearCanvas">清除</view>
<view class="modal-btn modal-confirm" bindtap="saveToImage">上传</view>
</view>
</view>
</view>
</view>
复制代码
2.signature组件样式
.signature-modal {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 3;
display: flex;
align-items: center;
justify-content: center;
}
.modal-mask{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 4;
background-color: rgba(0, 0, 0, .5);
}
.modal-content-area{
position: relative;
z-index: 5;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 700rpx;
min-height: 550rpx;
background-color: #ffffff;
border-radius: 18rpx;
}
.modal-content {
width: 100%;
height: 100%;
}
.modal-canvas {
width: 650rpx;
height: 420rpx;
margin: 0 auto;
margin-bottom: 30rpx;
border-radius: 18rpx;
box-sizing: border-box;
overflow: hidden;
background-color: rgba(0, 0, 0, .1);
}
.modal-bottom {
display: flex;
width: 100%;
height: 70rpx;
justify-content: space-between;
align-items: center;
background-color: #869ee9;
color: #ffffff;
}
.modal-btn {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 50%;
height: 100%;
}
.modal-btn:nth-child(1) {
border-right: 1rpx solid #ffffff;
}
复制代码
3.signature组件js文件
// component/signature/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
tempFilePath:'',
hideModal: true,
hasDraw: false,
canvasName: '#handWriting',
ctx: '',
canvasWidth: 0,
canvasHeight: 0,
startPoint: {
x: 0,
y: 0,
},
selectColor: 'black',
lineColor: '#1A1A1A', // 颜色
lineSize: 1, // 笔记倍数
radius: 5, //画圆的半径
},
lifetimes: {
ready() {
let that = this
let query = wx.createSelectorQuery().in(this); //获取自定义组件的SelectQuery对象
this.canvasCtx = wx.createCanvasContext('signature', that)
// 设置线的样式
this.canvasCtx.setLineCap("round");
this.canvasCtx.setLineJoin("round");
// 初始化颜色
this.canvasCtx.setStrokeStyle(that.data.selectColor);
// 初始化粗细
query.select('.modal-canvas').boundingClientRect(rect => {
this.setData({
canvasWidth: rect.width,
canvasHeight: rect.height,
});
}).exec();
}
},
/**
* 组件的方法列表
*/
methods: {
show() {
this.setData({
hideModal: false
})
},
closeModal() {
this.clearCanvas()
this.setData({
hideModal: true
})
this.triggerEvent('closeSignature')
},
scaleStart(event) {
if (event.type != 'touchstart') return false;
let currentPoint = {
x: event.touches[0].x,
y: event.touches[0].y
}
// this.data.ctx.moveTo(currentPoint.x, currentPoint.y)
this.drawCircle(currentPoint);
this.setData({
startPoint: currentPoint,
hasDraw: true, //签字了
});
},
mouseDown() {},
scaleEnd(e) {
this.setData({
isStart: true
})
},
scaleMove(event) {
if (event.type != "touchmove") return false;
let {
startPoint
} = this.data
let currentPoint = {
x: event.touches[0].x,
y: event.touches[0].y
}
this.drawLine(startPoint, currentPoint)
this.setData({
startPoint: currentPoint
})
},
drawCircle(point) { //这里负责点
let ctx = this.canvasCtx;
ctx.beginPath();
// ctx.fillStyle = this.data.lineColor;
ctx.setFillStyle(this.data.lineColor)
//笔迹粗细由圆的大小决定
ctx.arc(point.x, point.y, this.data.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath();
ctx.draw(true)
},
drawLine(sourcePoint, targetPoint) {
let ctx = this.canvasCtx;
this.drawCircle(targetPoint);
ctx.beginPath();
// ctx.strokeStyle = this.data.lineColor;
ctx.setStrokeStyle(this.data.lineColor)
// ctx.lineWidth = this.data.radius * 2; //这里乘2是因为线条的粗细要和圆的直径相等
ctx.setLineWidth(this.data.radius*2)
ctx.moveTo(sourcePoint.x, sourcePoint.y);
ctx.lineTo(targetPoint.x, targetPoint.y);
ctx.stroke();
ctx.closePath();
// ctx.draw()
},
clearCanvas() { //清空画布
let ctx = this.canvasCtx;
ctx.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeight);
ctx.fillStyle = 'rgba(0, 0, 0, .1)';
ctx.draw()
this.setData({
hasDraw: false //未签字
})
},
getTempFile(){
return {
tempFilePath:this.data.tempFilePath
}
},
saveToImage() {
let {
hasDraw,
canvasHeight,
canvasWidth
} = this.data
let that=this
if (!hasDraw) {
wx.showToast({
title: '还未签字哟!',
icon: 'none',
mask: true
})
return
}
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
canvasId: 'signature',
success(res) {
if(res.tempFilePath){
that.setData({
tempFilePath:res.tempFilePath
})
that.triggerEvent('confirm')
}
console.log(res.tempFilePath)
},
fail(err) {
console.log(err);
}
},that)
}
}
})
复制代码
ps:考虑到是之前的老项目,这里选择的Canvas版本为老版本的API,等有空了用新版的Canvas实现一下
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END