1. 概述
微信小程序开发已经成为了现阶段最火的开发方式之一,在这其中的手势解锁功能也是非常常见的,它可以为小程序增加一些非常好玩、有趣、实用的交互体验,以此来增强用户对小程序的喜爱度和留存率。
2. 手势解锁的实现原理
2.1 手势解锁的数据结构
手势解锁的数据结构一般采用二维数组作为存储方式,以九宫格为例,二维数组中的每一个位置都对应着九宫格中一个的点,该位置存储的则是该点对应的状态,通常将状态分为 3 种,包括:
- 0,表示该点没有被选中
- 1,表示该点被选中
- 2,表示该点被选中并且是高亮状态
例如下面这个二维数组表示一个 3 * 3 的九宫格中,其中的第一行三个点被选中,且第一个点是高亮状态:
[
[2, 1, 1],
[0, 0, 0],
[0, 0, 0]
]
2.2 手势解锁的事件处理
手势解锁的事件处理需要用到小程序中的手势事件,常见的有以下几种:
- touchstart:手指触摸屏幕时触发
- touchmove:手指在屏幕上移动时触发
- touchend:手指离开屏幕时触发
当用户触摸屏幕时,需要根据当前手指所在的位置计算出当前手指所在的点,并将该点的状态设置为 1,然后将该点的信息保存下来。当手指移动时,需要不断地计算当前手指所在的点,并将每个点的状态都设置为 1,这样就可以实现连线效果。最后当手指离开屏幕时,需要将所有点的状态都重新设置为 0,同时触发一个验证事件来判断用户绘制的手势是否正确。
3. 手势解锁的具体实现
3.1 绘制九宫格
为了方便用户选择手势解锁的起点和终点,需要在页面上绘制一个九宫格,代码如下:
<canvas bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" style="width: 100%; height: 100%;"></canvas>
在 touchStart 事件处理函数中,需要获取到画布的上下文对象,并且绘制出九宫格的边框和所有的圆点。代码如下:
touchStart: function (e) {
var context = wx.createCanvasContext('unlock-pattern', this)
// 计算 canvas 的宽度和高度以及每个圆圈的半径
var width = wx.getSystemInfoSync().windowWidth
var radius = Math.round(width * 0.06)
var spacing = Math.round((width - 6 * radius) / 4)
// 绘制九宫格的边框和所有圆圈
context.setStrokeStyle('#999')
context.setLineWidth(2)
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var x = j * (radius * 2 + spacing) + radius + 10
var y = i * (radius * 2 + spacing) + radius + 200
context.strokeRect(x - radius, y - radius, radius * 2, radius * 2)
context.beginPath()
context.arc(x, y, radius, 0, 2 * Math.PI, true)
context.closePath()
context.stroke()
}
}
context.draw()
},
上面的代码中,通过调用 wx.createCanvasContext 方法来获取到上下文对象,然后计算出每个圆圈的位置,并绘制出所有的圆点和九宫格的边框。最后调用 draw 方法来将画布绘制出来。
3.2 绘制所有选中的圆圈
在用户绘制手势过程中,需要不断更新画布上圆圈的状态,具体可以在 touchMove 事件中实现,代码如下:
touchMove: function (e) {
var context = wx.createCanvasContext('unlock-pattern', this)
// 计算手指在画布上的坐标和屏幕的宽度
var x = e.touches[0].x
var y = e.touches[0].y
var width = wx.getSystemInfoSync().windowWidth
// 计算每个圆圈的半径和间距
var radius = Math.round(width * 0.06)
var spacing = Math.round((width - 6 * radius) / 4)
// 遍历每个圆圈,判断当前手指是否在圆圈内,并且将圆圈的状态设置为 1
var selected = []
context.setStrokeStyle('#999')
context.setLineWidth(2)
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var x1 = j * (radius * 2 + spacing) + radius + 10
var y1 = i * (radius * 2 + spacing) + radius + 200
var d = Math.sqrt(Math.pow(x1 - x, 2) + Math.pow(y1 - y, 2))
if (d <= radius) {
selected.push([i, j])
context.beginPath()
context.arc(x1, y1, radius - 5, 0, 2 * Math.PI, true)
context.closePath()
context.stroke()
}
}
}
// 将画布更新
context.draw()
// 将当前选中的点的状态设置为 1,并且将信息保存下来
for (var i = 0; i < selected.length; i++) {
var a = selected[i][0]
var b = selected[i][1]
if (this.data.pattern[a][b] === 0) {
this.data.pattern[a][b] = 1
this.data.selected.push([a, b])
}
}
},
3.3 显示已经选中的圆圈
在用户绘制手势过程中,需要不断更新画布上圆圈的状态,具体可以在 touchMove 事件中实现,代码如下:
drawSelected: function () {
var context = wx.createCanvasContext('unlock-pattern', this)
// 计算屏幕的宽度和每个圆圈的半径和间距
var width = wx.getSystemInfoSync().windowWidth
var radius = Math.round(width * 0.06)
var spacing = Math.round((width - 6 * radius) / 4)
// 绘制已经选中的圆圈
context.setStrokeStyle('#3E7FE0')
context.setLineWidth(2)
context.beginPath()
for (var i = 0; i < this.data.selected.length; i++) {
var a = this.data.selected[i][0]
var b = this.data.selected[i][1]
var x1 = b * (radius * 2 + spacing) + radius + 10
var y1 = a * (radius * 2 + spacing) + radius + 200
if (i === 0) {
context.moveTo(x1, y1)
} else {
context.lineTo(x1, y1)
}
}
context.stroke()
context.draw(true)
},
在上面的代码中,遍历已经选中的圆点,将这些圆点连接起来,然后使用 draw 方法将绘制的内容实时显示在画布上。
3.4 校验用户绘制的手势
当用户绘制完手势后,需要验证用户绘制的手势是否正确,具体可在 touchEnd 事件中进行处理,代码如下:
touchEnd: function (e) {
// 校验用户绘制的手势
// 代码略
// 将所有点的状态都重新设置为 0,并且清空已选中的点的信息
this.setData({
pattern: [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
],
selected: []
})
// 将画布的状态还原
var context = wx.createCanvasContext('unlock-pattern', this)
context.draw()
}
4. 总结
手势解锁功能已经被广泛应用于各类移动设备中,它不仅能够增加用户的交互体验,还能够提高应用的安全性。本文详细介绍了微信小程序手势解锁功能的实现原理和具体实现方法,希望能对初学者提供一些参考价值。