HarmonyOS 實現(xiàn)一個滑塊驗證
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
前言
日常我們經(jīng)常能見到驗證碼,網(wǎng)站上的驗證碼的作用是保護網(wǎng)站安全,一般網(wǎng)站都要通過驗證碼來防止機器大規(guī)模注冊等危害。一般驗證碼有:圖像驗證、算數(shù)驗證、滑動驗證等。有些驗證碼驗證起來有些麻煩,對我來說,最方便的驗證方式是滑動滑塊驗證,滑塊驗證的使用體驗非常好。
所以本篇文章我來嘗試著實現(xiàn)一個滑動驗證碼。當然,這種驗證碼一般都是第三方來處理的,因為它不僅僅只是滑動,還會判斷用戶的拖放軌跡是否符合真實用戶的行為特征,所以我只是簡單的實現(xiàn)。
介紹
這是一個滑塊驗證碼,用戶只需要將滑塊滑到最右側(cè),即可判斷用戶是否驗證成功。
效果展示
我為滑塊驗證添加了驗證條件,用戶可以對滑塊速度做限制,例如:滑塊滑倒右側(cè)時,平均速度小于3,如果用戶滑動速度大于3時,就驗證失敗。
我一共滑動了三次:
- 第一次:沒有滑倒最右側(cè),認證失敗。
- 第二次:滑動的速度太塊,認證失敗。
- 第三次:滑動速度符合限制,認證成功。
使用
1、參數(shù)支持
參數(shù)名稱 | 參數(shù)描述 | 參數(shù)類型 | 默認值 |
width | 滑塊寬度 | Number | 300 |
height | 滑塊高度 | Number | 50 |
limit | 滑塊的速率限制 | Number | 4 |
2、事件支持
事件名稱 | 事件描述 |
getMsg | 驗證通過或不通過事件 |
用戶可以設(shè)置限制體速率,可以通過自定義事件getMsg,獲取到驗證的結(jié)果。
原理分析
1、滑動原理
首先,我們需要在組件加載完成時,獲取到滑塊可以滑動的最大距離,我們用得到的最大距離,來判斷滑塊是否滑倒最右側(cè)
注意組件的生命周期,在自定義組件中,是沒有onShow的,需要用onLayoutReady(),這個鉤子函數(shù)是自定義組件布局完成調(diào)用的。
然后,在觸摸屏幕事件中,獲取觸摸的X坐標,此坐標為起始點;在觸摸移動事件中,獲取最新的X坐標,再減去起始坐標,就能得到偏移量。
最后,判斷偏移量是否大于滑塊可以滑動的最大距離,如果不大于,將偏移量設(shè)置為滑塊的滑動距離。
為了更好理解,我把滑塊隱藏部分顯示出來。
touchstart (e) {
//設(shè)置X軸的始點
this.startPositionX = e.touches[0].localX;
this.startTime = 0
this.s = 0
this.num = 0
},
//滑塊移動中執(zhí)行的事件
touchmove (e) {
const offsetX = e.touches[0].localX - this.startPositionX
// 如果驗證成功后仍允許滑動,則執(zhí)行下面代碼塊(初始值默認為允許)
if (this.isSlide) {
//當x坐標大于最大可移動距離,那么當前x坐標即為最大可移動距離
if (offsetX >= this.max) {
this.x = this.max
} else {
// 將當前鼠標x坐標給滑塊移動的距離
this.x = offsetX;
}
}
},
2、驗證原理
這里的驗證不嚴謹,只是一個小嘗試。
驗證原理主要是通過滑動的平均速度來判斷的,如果用戶滑動速度超過設(shè)定速度,則驗證失敗。
所以我們需要使用到時間戳。
第一步,我們在移動事件一開始,獲取到當前的時間戳;在移動事件結(jié)束將當前時間戳賦值給上一個時間,這樣通過當前時間戳 -上一個時間就能獲取到時間間隔。
第二步,我們還需要獲取到偏移量,上面滑動原理已經(jīng)介紹了如何獲取。
第三步,有了時間間隔和偏移量,我們可以計算出本次滑動的速度,再利用總的滑動次數(shù)來獲取到平均速度。
最后,我們只需要在touchend事件中做判斷,判斷滑塊是否到達滑動的最大距離,并且滑塊滑動的平均速度是否符合限制。
touchmove (e) {
const offsetX = e.touches[0].localX - this.startPositionX
const currTime = Date.now()
if (this.startTime !== 0) {
const duration = currTime - this.startTime
// 傳入倒數(shù)第二個點和最后一個點,和持續(xù)時間,會返回加速度
const v = parseInt(offsetX / duration)
this.num++
this.s = this.s + v
}
this.startTime = currTime
// 如果驗證成功后仍允許滑動,則執(zhí)行下面代碼塊(初始值默認為允許)
if (this.isSlide) {
//當x坐標大于最大可移動距離,那么當前x坐標即為最大可移動距離
if (offsetX >= this.max) {
this.x = this.max
} else {
// 將當前鼠標x坐標給滑塊移動的距離
this.x = offsetX;
}
}
},
//松開滑塊執(zhí)行的事件
touchend (e) {
// 計算平均速度
const avg = this.s / this.num
console.log(avg)
//自定義組件觸發(fā)事件時提供的data對象
var data = {};
//如果觸摸的X軸坐標大于等于限定的可移動范圍,并且滑動的平均速度不能超過100,則驗證成功
if (this.x == this.max && avg < this.limit) {
//設(shè)置驗證成功提示語
this.status = '驗證成功';
//設(shè)置data對象的返回值
data.msg = true;
//驗證成功后,禁止滑塊滑動
this.isSlide = false;
} else {
//元素X軸坐標歸0
this.x = 0;
//清空驗證成功提示語
this.status = '';
this.tip = '驗證失敗'
//設(shè)置data對象的返回值
data.msg = false;
}
this.$emit('getMsg', data)
}
完整代碼
index.js:
// @ts-nocheck
export default{
data:{
tip: '右滑驗證',
x: 0,//X軸的初始值
startPositionX: 0,//觸摸時X軸的值
max: 0,//滑塊可移動的X軸范圍
status: '',//驗證完后的提示信息
isSlide: true,//是否允許驗證成功后繼續(xù)滑動
positionList: {}, // 存儲坐標位置
startTime: 0,
num: 0, // 總次數(shù)
s: 0 // 速度之和
},
props: {
limit: {
type: Number,
default: 4
},
width: {
type: Number,
default: 400
},
height: {
type: Number,
default: 100
}
},
onLayoutReady(){
let ball = this.$element("ball")
let box = this.$refs.container
// 滑塊可以移動的最大距離
this.max = box.getBoundingClientRect().width - ball.getBoundingClientRect().width
},
touchstart (e) {
//設(shè)置X軸的始點
this.startPositionX = e.touches[0].localX;
this.startTime = 0
this.s = 0
this.num = 0
},
//滑塊移動中執(zhí)行的事件
touchmove (e) {
const offsetX = e.touches[0].localX - this.startPositionX
const currTime = Date.now()
if (this.startTime !== 0) {
const duration = currTime - this.startTime
// 傳入倒數(shù)第二個點和最后一個點,和持續(xù)時間,會返回加速度
const v = parseInt(offsetX / duration)
this.num++
this.s = this.s + v
}
this.startTime = currTime
// 如果驗證成功后仍允許滑動,則執(zhí)行下面代碼塊(初始值默認為允許)
if (this.isSlide) {
//當x坐標大于最大可移動距離,那么當前x坐標即為最大可移動距離
if (offsetX >= this.max) {
this.x = this.max
} else {
// 將當前鼠標x坐標給滑塊移動的距離
this.x = offsetX;
}
}
},
//松開滑塊執(zhí)行的事件
touchend (e) {
// 計算平均速度
const avg = this.s / this.num
//自定義組件觸發(fā)事件時提供的data對象
var msg = {};
//如果觸摸的X軸坐標大于等于限定的可移動范圍,并且滑動的平均速度不能超過100,則驗證成功
if (this.x == this.max && avg < this.limit) {
//設(shè)置驗證成功提示語
this.status = '驗證成功';
//設(shè)置data對象的返回值
msg = true;
//驗證成功后,禁止滑塊滑動
this.isSlide = false;
} else {
//元素X軸坐標歸0
this.x = 0;
//清空驗證成功提示語
this.status = '';
this.tip = '驗證失敗'
//設(shè)置data對象的返回值
msg = false;
}
this.$emit('getMsg', msg)
}
}
總結(jié)
不足點:驗證條件比較簡單。
文章相關(guān)附件可以點擊下面的原文鏈接前往下載:
https://ost.51cto.com/resource/2234。