原生js實(shí)現(xiàn)拖動(dòng)滑塊驗(yàn)證題
前言
驗(yàn)證的目的是為了減輕超高數(shù)據(jù)量的訪問(wèn)時(shí),服務(wù)器的壓力,減少同時(shí)請(qǐng)求量尤辱;前端基本都不能避免與驗(yàn)證打交道,這里記錄一下我對(duì)于滑塊驗(yàn)證的學(xué)習(xí)過(guò)程钻蔑。
思路
作為前端啥刻,我們要將自己帶入用戶的角度,對(duì)用戶的操作習(xí)慣進(jìn)行考慮咪笑,我將拖動(dòng)滑塊驗(yàn)證功能歸納為:三個(gè)事件可帽、驗(yàn)證成功、驗(yàn)證失敗窗怒。
- 按住滑塊才能開(kāi)始拖動(dòng)(按下映跟、移動(dòng)蓄拣、松開(kāi)事件)
- 驗(yàn)證成功后不能再拖動(dòng)(跳轉(zhuǎn)頁(yè)面或禁用)
- 驗(yàn)證失敗時(shí),滑塊回歸原始位置(拖動(dòng)到一半松開(kāi))
代碼結(jié)構(gòu)
HTML結(jié)構(gòu):box -> 滑塊+文字+背景
滑塊移動(dòng)思路
box position:relative
滑塊 position:absolute
-
拖動(dòng)滑塊努隙,讓滑塊的絕對(duì)定位left隨鼠標(biāo)坐標(biāo)而改變球恤,造成移動(dòng)效果
通過(guò)evevt事件可以獲取到當(dāng)前X軸和Y軸坐標(biāo),event.clientX;clientY
event.clientX;clientY 是從屏幕左上角開(kāi)始的坐標(biāo)
滑塊移動(dòng)距離(left) = 用移動(dòng)時(shí)鼠標(biāo)的坐標(biāo) - 最開(kāi)始鼠標(biāo)按下的坐標(biāo)
clipboard.png -
控制滑塊移動(dòng)的范圍荸镊,不超出box
(moveX >= 0 && moveX <= (boxWidth - btnWidth)
btn.style.left = (boxWidth - btnWidth) + 'px'
滑塊可移動(dòng)的范圍moveX如圖所示咽斧,在0到(box的寬度 - 滑塊的寬度)之間
clipboard2.png 滑動(dòng)途中,背景的寬度改變
背景的寬度與滑塊可移動(dòng)范圍moveX相同
bg.style.width = (boxWidth - btnWidth) + 'px'
滑動(dòng)到尾部時(shí)要文字替換+事件清除(按下躬存、移動(dòng)张惹、松開(kāi))
鼠標(biāo)松開(kāi),滑塊回到原點(diǎn)岭洲,清除移動(dòng)事件(不清除按下事件宛逗,否則之后不能按下)
最后上代碼
HTML
<div class="box">
<div class="btn">>></div>
<p class="text">拖動(dòng)滑塊驗(yàn)證</p>
<div class="bg"></div>
</div>
CSS
* {
margin: 0;
padding: 0;
background-color: #ffffff;
}
.box {
width: 500px;
height: 60px;
position: relative;
left: 50%;
margin-left: -250px;
margin-top: 50px;
background: #eae4e4;
display: flex;
align-items: center;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
.btn {
height: 100%;
width: 60px;
background: #fbf5f5;
box-sizing: border-box;
border: 2px solid #cecaca;
position: absolute;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 25px;
color: #d5d4d4;
z-index: 999;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
.btn:hover {
cursor:pointer;
}
.text {
font-size: 20px;
position: absolute;
left: 50%;
margin-left: -60px;
background-color: transparent;
z-index: 2;
}
.bg {
height: 100%;
position: absolute;
background-color: #4cbb42;
z-index: 1;
}
JS
window.onload = function () {
// 封裝-選擇器,內(nèi)部可以做兼容性
function querySelect(name) {
return document.querySelector(name)
}
// 驗(yàn)證成功
// 驗(yàn)證失敗
// 觸發(fā)事件 onmousedown按下 onmousemove移動(dòng) onmouseup松開(kāi)
let btn = querySelect('.btn') // 滑塊 對(duì)IE6/7 有兼容性問(wèn)題
let box = querySelect('.box') // box
let text = querySelect('.text') // 文字
let bg = querySelect('.bg') // 背景
btn.onmousedown = (eventDown) => {
// event.clientX;clientY 鼠標(biāo)當(dāng)前X軸Y軸坐標(biāo)
let downX = eventDown.clientX
console.log(downX)
document.onmousemove = (eventMove) => {
// 移動(dòng)的X坐標(biāo) - 按下的X坐標(biāo)
let moveX = eventMove.clientX - downX
let boxWidth = box.offsetWidth
let btnWidth = btn.offsetWidth
if (moveX >= 0 && moveX <= (boxWidth - btnWidth)) { // 可移動(dòng)的范圍
btn.style.left = moveX + 'px' // 滑塊絕對(duì)定位
bg.style.width = moveX + 'px' // 設(shè)備背景的寬度
}
if (moveX >= (boxWidth - btnWidth)) {
btn.style.left = (boxWidth - btnWidth) + 'px' // 滑塊絕對(duì)定位
bg.style.width = (boxWidth - btnWidth) + 'px' // 設(shè)備背景的寬度
// 文字提醒
text.innerText = '驗(yàn)證成功'
text.style.color = '#fff'
// 事件清除-按下、移動(dòng)
btn.onmousedown = null
document.onmousemove = null
btn.onmouseup = null
}
}
}
btn.onmouseup = (eventUp) => {
// 松開(kāi)后回到原點(diǎn)
// 清除移動(dòng)事件
btn.style.left = 0 + 'px'
bg.style.width = 0 + 'px'
document.onmousemove = null
}
}