1. 前言
手势密码是一种很常见的安全验证方式,现在很多应用都会采用这种方式,如手机解锁等。本文主要介绍如何在uniapp中实现手势密码功能。我们会使用uniapp自带的touchstart、touchmove和touchend事件来实现这个功能。
2. 实现过程
2.1 创建手势密码页面
我们先创建一个手势密码的页面,包含一个画布和一些必要的变量。画布用来绘制手势密码,变量用来保存手势密码的状态和路径等信息。
// 创建手势密码页面的vue实例
<template>
<view class="gesture-container">
<canvas canvas-id="gesture-canvas" @touchstart="canvasTouchStart" @touchmove="canvasTouchMove"
@touchend="canvasTouchEnd"></canvas>
</view>
</template>
<script>
export default {
data() {
return {
// 画布的宽度和高度
canvasWidth: 0,
canvasHeight: 0,
// 手势密码的状态
status: 'normal', // 初始状态
message: '请输入手势密码', // 状态提示信息
// 手势密码的路径
path: [],
lastX: null,
lastY: null,
}
}
}
</script>
在上面的代码中,我们创建了一个名为gesture-container的页面容器,其中包含了一个canvas标签,用于绘制手势密码。我们还声明了一些变量,包括canvas的宽度和高度,手势密码的状态(包括normal、right和wrong等状态)、提示信息以及手势密码的路径,以及最后一个点的坐标。
2.2 绘制手势密码
接下来,我们需要实现绘制手势密码的功能。首先,我们需要在touchstart事件里记录下手指的起始坐标,并且设置手势密码的状态为normal状态。
canvasTouchStart(e) {
const { x, y } = this.getEventPosition(e)
this.status = 'normal'
this.message = '请输入手势密码'
this.lastX = x
this.lastY = y
this.path = [{ x, y }]
}
在touchmove事件里,我们需要绘制手势密码的路径,为了避免重复绘制,我们需要判断当前点是否已经在路径中出现过,在这种情况下,我们不需要再绘制当前点,否则,我们需要通过path的push方法将当前点加入路径中,并且在当前点和上一个点之间绘制一条线段。
canvasTouchMove(e) {
if (this.status === 'right') {
return
}
const { x, y } = this.getEventPosition(e)
const point = { x, y }
const lastPoint = this.path[this.path.length - 1]
if (lastPoint.x !== point.x || lastPoint.y !== point.y) {
this.path.push(point)
this.drawLine(lastPoint.x, lastPoint.y, x, y)
}
this.lastX = x
this.lastY = y
}
在touchend事件里,我们需要判断手势密码是否正确,如果正确,则设置手势密码的状态为right状态,并且提示手势密码已经设置成功,否则,设置手势密码的状态为wrong状态,并且提示手势密码设置失败,需要重新输入。我们还需要将画布上的路径清除。
canvasTouchEnd() {
if (this.path.length <= 1) {
return
}
const password = this.getLocalPassword() // 获取本地存储的手势密码
if (password) {
const psw = this.getPathString(this.path) // 将path转换为字符串
if (psw === password) {
this.status = 'right'
this.message = '手势密码设置成功'
this.saveLocalPassword(psw) // 保存手势密码到本地
setTimeout(() => {
// 成功后跳转
uni.redirectTo({ url: '/pages/index/index' })
}, 1000)
} else {
this.status = 'wrong'
this.message = '手势密码设置失败,请重新输入'
this.clearCanvas() // 清除画布上的路径
setTimeout(() => {
this.status = 'normal'
this.message = '请输入手势密码'
}, 1000)
}
} else {
const psw = this.getPathString(this.path)
this.status = 'normal'
this.message = '请再次输入手势密码'
this.saveLocalPassword(psw)
setTimeout(() => {
this.clearCanvas() // 清除画布上的路径
this.path = []
this.lastX = null
this.lastY = null
}, 1000)
}
}
2.3 其他功能
我们还可以添加一些其他的功能,如用来清除画布上的路径的clearCanvas方法,用来获取鼠标或手指相对于画布左上角的坐标的getEventPosition方法,以及用来将path转换为字符串的getPathString方法等。
clearCanvas() {
const ctx = uni.createCanvasContext('gesture-canvas', this)
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
ctx.draw(false)
},
getEventPosition(event) {
const { clientX, clientY } = event.touches[0]
const { left, top } = uni.createSelectorQuery()
.in(this)
.select('.gesture-container')
.boundingClientRectSync()
const x = clientX - left
const y = clientY - top
return { x, y }
},
getPathString(path) {
return path.map(p => `${p.x},${p.y}`).join('-')
},
// 获取本地存储的手势密码
getLocalPassword() {
return uni.getStorageSync('gesture_password') || ''
},
// 保存手势密码到本地
saveLocalPassword(password) {
uni.setStorageSync('gesture_password', password)
}
3. 总结
在上面的代码中,我们使用了uniapp自带的touchstart、touchmove和touchend事件实现了手势密码的功能。我们在touchstart事件里记录下起始点的坐标,在touchmove事件里绘制手势密码的路径,并在touchend事件中判断手势密码是否正确,并对画布进行清除等操作。通过以上的步骤,我们可以轻松地实现手势密码功能。