今年入职了一家公司做前端,专门写微信小程序,现在开发告一段落,也终于有空总结一下开发过程中遇到的问题和一些收获,今天分享一个手写签名的组件实现方法。
先看效果,实现了一个横屏的手写签名组件
无数据:

手写以后

实现步骤,及代码
-
第一步 创建一个 signature 文件
-
第二步 创建四个文件名称分别为,index.js、index.json、index.wxml、index.wxss
-
第三步 在index.json中声明 "component": true
使用
1、在父组件的json中引入组件 并且将 pageOrientation 设置为 true 否则不会横屏
json
{
"usingComponents": {
"signature": "/components/signature/index"
},
"pageOrientation": "landscape"
}
2、父组件的html中直接引入就好
xml
<view>
<signature></signature>
</view>
代码部分
index.wxml
html
<view class="modal-content-area">
<view class="modal-content">
<view class="toast" wx:if="{{!hasDraw}}">
请工整地写出自己的姓名~
</view>
<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="clear_signature" bindtap="">
</view>
<view class="flex_btn">
<view class="modal-btn modal-clear" bindtap="clearCanvas">清除</view>
<view class="modal-btn modal-confirm" bindtap="save">确认</view>
</view>
</view>
</view>
</view>
</view>
index.wxss
css
.signature-modal {
width: 100vw;
height: 100vh;
overflow: hidden;
z-index: 3;
background: blue;
}
.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 {
z-index: 5;
width: 100%;
height: 100%;
background: #F5F7FB;
position: absolute;
}
.modal-content {
width: 100%;
height: 100%;
background: #ffffff;
}
.modal-canvas {
width: 100vw;
height: 83vh;
background: #F5F7FB !important;
border: 1rpx solid rgba(0, 0, 0, 0.08);
border-radius: 4rpx;
z-index: 1;
}
.modal-bottom {
position: absolute;
bottom: 15rpx;
display: flex;
align-items: center;
justify-content: space-between;
z-index: 100;
width: 100vw;
box-sizing: border-box;
padding: 0 32rpx;
}
.modal-btn {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 85rpx;
height: 30rpx;
background: rgba(103, 149, 255, 0.2);
}
.modal-clear {
font-size: 13rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #3670F5;
margin-right: 12rpx;
}
.modal-confirm {
background: #3670F5;
font-size: 13rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
}
.modal-btn:nth-child(1) {
border-right: 1rpx solid #ffffff;
}
.clear_signature {
/* position: absolute; */
top: 40rpx;
right: 15rpx;
display: flex;
align-items: center;
z-index: 1;
font-size: 13rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #3670F5;
/* background-color: #F5F7FB; */
z-index: 100;
}
.clear_signature>text {
height: 17rpx;
}
.clear_signature>image {
width: 15rpx;
height: 15rpx;
margin-right: 2rpx;
}
.toast {
position: absolute;
top: 40%;
left: 42%;
transform: rotate(-50%, -50%);
z-index: 100;
font-size: 13rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(58, 65, 85, 0.4);
}
.flex_btn {
display: flex;
align-items: center;
}
index.js
js
Component({
/**
* 组件的初始数据
*/
data: {
tempFilePath: '',
hideModal: false,
hasDraw: false,
canvasName: '#handWriting',
ctx: '',
canvasWidth: 0,
canvasHeight: 0,
startPoint: {
x: 0,
y: 0,
},
selectColor: 'black',
lineColor: '#1A1A1A', // 颜色
lineSize: 1, // 笔记倍数
radius: 5, //画圆的半径
},
// 初始化画布
ready() {
this.setData({
hideModal: false
})
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: {
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.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.setStrokeStyle(this.data.lineColor)
ctx.setLineWidth(this.data.radius * 2)
ctx.moveTo(sourcePoint.x, sourcePoint.y);
ctx.lineTo(targetPoint.x, targetPoint.y);
ctx.stroke();
ctx.closePath();
},
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 //未签字
})
},
save() {
let {
hasDraw,
} = this.data
if (!hasDraw) {
wx.showToast({
title: '还未签字哟!',
icon: 'none',
mask: true
})
return
} else {
this.saveToImage();
}
},
saveToImage() {
let that = this;
let {
canvasHeight,
canvasWidth
} = that.data;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
canvasId: 'signature',
success(res) {
console.log(res.tempFilePath, "res.tempFilePath");
if (res.tempFilePath) {
that.setData({
tempFilePath: res.tempFilePath
})
}
},
fail(err) {
console.log(err);
}
}, that)
}
}
})
index.json
json
{
"usingComponents": {},
"component": true
}