【微信小程式canvas】實現小程式手寫板使用者簽名(附程式碼)
工作中公司業務需要的微信小程式使用者簽字功能
先看效果圖:
wxml
<view class="wrapper">
<view class="handBtn">
<button catchtap="retDraw" class="delBtn">重寫</button>
<button catchtap="subCanvas" class="subBtn">完成</button>
</view>
<view class="handCenter">
<canvas class="handWriting" disable-scroll="true" bindtouchstart="uploadScaleStart" bindtouchmove="uploadScaleMove"
bindtouchend="uploadScaleEnd" bindtap="mouseDown" canvas-id="handWriting">
</canvas>
</view>
<view class="handRight">
<view class="handTitle">手寫板</view>
</view>
</view>
複製程式碼
js
data
page({
data: {
canvasName: 'handWriting',
ctx: '',
canvasWidth: 0,
canvasHeight: 0,
transparent: 1, // 透明度
selectColor: 'black',
lineColor: '#1A1A1A', // 顏色
lineSize: 1.5, // 筆記倍數
lineMin: 0.5, // 最小筆畫半徑
lineMax: 4, // 最大筆畫半徑
pressure: 1, // 預設壓力
smoothness: 60, //順滑度,用60的距離來計算速度
currentPoint: {},
currentLine: [], // 當前線條
firstTouch: true, // 第一次觸發
radius: 1, //畫圓的半徑
cutArea: { top: 0, right: 0, bottom: 0, left: 0 }, //裁剪區域
bethelPoint: [], //儲存所有線條 生成的貝塞爾點;
lastPoint: 0,
chirography: [], //筆跡
currentChirography: {}, //當前筆跡
linePrack: [], //劃線軌跡 , 生成線條的實際點
}
})
複製程式碼
初始化
page({
onLoad () {
let canvasName = this.data.canvasName
let ctx = wx.createCanvasContext(canvasName)
this.setData({
ctx: ctx
})
var query = wx.createSelectorQuery();
query.select('.handCenter').boundingClientRect(rect => {query.select('.handCenter').boundingClientRect(rect => {
this.setData({this.setData({
canvasWidth: rect.width,canvasWidth: rect.width,
canvasHeight: rect.heightcanvasHeight: rect.height
})})
}).exec(); }).exec();
}, },
})
複製程式碼
事件函式
筆跡開始
// 筆跡開始
uploadScaleStart (e) {
if (e.type != 'touchstart') return false;
let ctx = this.data.ctx;
ctx.setFillStyle(this.data.lineColor); // 初始線條設定顏色
ctx.setGlobalAlpha(this.data.transparent); // 設定半透明
let currentPoint = {
x: e.touches[0].x,
y: e.touches[0].y
}
let currentLine = this.data.currentLine;
currentLine.unshift({
time: new Date().getTime(),
dis: 0,
x: currentPoint.x,
y: currentPoint.y
})
this.setData({
currentPoint,
// currentLine
})
if (this.data.firstTouch) {
this.setData({
cutArea: { top: currentPoint.y, right: currentPoint.x, bottom: currentPoint.y, left: currentPoint.x },
firstTouch: false
})
}
this.pointToLine(currentLine);
},
複製程式碼
筆跡移動
// 筆跡移動
uploadScaleMove (e) {
if (e.type != 'touchmove') return false;
if (e.cancelable) {
// 判斷預設行為是否已經被禁用
if (!e.defaultPrevented) {
e.preventDefault();
}
}
let point = {
x: e.touches[0].x,
y: e.touches[0].y
}
//測試裁剪
if (point.y < this.data.cutArea.top) {
this.data.cutArea.top = point.y;
}
if (point.y < 0) this.data.cutArea.top = 0;
if (point.x > this.data.cutArea.right) {
this.data.cutArea.right = point.x;
}
if (this.data.canvasWidth - point.x <= 0) {
this.data.cutArea.right = this.data.canvasWidth;
}
if (point.y > this.data.cutArea.bottom) {
this.data.cutArea.bottom = point.y;
}
if (this.data.canvasHeight - point.y <= 0) {
this.data.cutArea.bottom = this.data.canvasHeight;
}
if (point.x < this.data.cutArea.left) {
this.data.cutArea.left = point.x;
}
if (point.x < 0) this.data.cutArea.left = 0;
this.setData({
lastPoint: this.data.currentPoint,
currentPoint: point
})
let currentLine = this.data.currentLine
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.data.currentPoint, this.data.lastPoint),
x: point.x,
y: point.y
})
// this.setData({
// currentLine
// })
this.pointToLine(currentLine);
},
複製程式碼
筆跡結束
// 筆跡結束
uploadScaleEnd (e) {
if (e.type != 'touchend') return 0;
let point = {
x: e.changedTouches[0].x,
y: e.changedTouches[0].y
}
this.setData({
lastPoint: this.data.currentPoint,
currentPoint: point
})
let currentLine = this.data.currentLine
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.data.currentPoint, this.data.lastPoint),
x: point.x,
y: point.y
})
// this.setData({
// currentLine
// })
if (currentLine.length > 2) {
var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
//$("#info").text(info.toFixed(2));
}
//一筆結束,儲存筆跡的座標點,清空,當前筆跡
//增加判斷是否在手寫區域;
this.pointToLine(currentLine);
var currentChirography = {
lineSize: this.data.lineSize,
lineColor: this.data.lineColor
};
var chirography = this.data.chirography
chirography.unshift(currentChirography);
this.setData({
chirography
})
var linePrack = this.data.linePrack
linePrack.unshift(this.data.currentLine);
this.setData({
linePrack,
currentLine: []
})
},
複製程式碼
wxss
page {
background: #fbfbfb;
height: auto;
overflow: hidden;
}
.wrapper {
width: 100%;
height: 95vh;
margin: 30rpx 0;
overflow: hidden;
display: flex;
align-content: center;
flex-direction: row;
justify-content: center;
font-size: 28rpx;
}
.handWriting {
background: #fff;
width: 100%;
height: 95vh;
}
.handRight {
display: inline-flex;
align-items: center;
}
.handCenter {
border: 4rpx dashed #e9e9e9;
flex: 5;
overflow: hidden;
box-sizing: border-box;
}
.handTitle {
transform: rotate(90deg);
flex: 1;
color: #666;
}
.handBtn button {
font-size: 28rpx;
}
.handBtn {
height: 95vh;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
align-content: space-between;
flex: 1;
}
.delBtn {
position: absolute;
top: 550rpx;
left: 0rpx;
transform: rotate(90deg);
color: #666;
}
.delBtn image {
position: absolute;
top: 13rpx;
left: 25rpx;
}
複製程式碼
結語
詳細專案程式碼handwriting-weapp(微信小程式原生canvas使用者簽字手寫板,後續更新計劃元件化、優化渲染邏輯、增加功能,歡迎start 和 PR)