JavaScript實(shí)現(xiàn)登錄拼圖驗(yàn)證的示例代碼
看到一個(gè)好文,所以模仿這實(shí)現(xiàn)一個(gè)登錄時(shí)的拼圖驗(yàn)證。效果展示如下。

底圖實(shí)現(xiàn)
首先實(shí)現(xiàn)一個(gè)盒子,存放我的

// html
<div class="check">
</div>// css
.check {
width: 400px;
height: 300px;
background-image: url(./img/bg.avif);
background-size: 100% 100%;
background-repeat: no-repeat;
position: relative;
filter: brightness(80%);
}底圖中的驗(yàn)證區(qū)域通過偽類實(shí)現(xiàn)

.check::before {
position: absolute;
content: '';
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.5);
top: 100px;
left: 280px;
}被驗(yàn)證區(qū)域塊
被驗(yàn)證區(qū)域有點(diǎn)類似于摳圖的概念了,通過從底圖中截取一部分,并且改變放置的位置,使其看起來是整體的一部分。核心的思想就是利用了background-position設(shè)置負(fù)值,獲取圖片的部分
<div class="check">
<!-- 驗(yàn)證區(qū)塊通過偽類實(shí)現(xiàn) -->
<!-- 被驗(yàn)證區(qū)塊 -->
<div class="check-box" id="check-box"></div>
</div> .check-box {
width: 50px;
height: 50px;
position: absolute;
top: 100px;
left: 0;
background-image: inherit;
background-repeat: inherit;
background-size: 400px 300px;
background-position: -280px -100px;
border: 1px solid #fff;
}滑塊區(qū)域
滑塊的html+css實(shí)現(xiàn)特別簡單,這里有一個(gè)對號是通過border-width實(shí)現(xiàn)的,感覺很妙呀!
<!-- 拖動條 -->
<div class="drag">
<!-- 滑塊 -->
<div class="drag-box" id="drag-box">
<!-- 對號 -->
<div id="drag-mark" class="drag-mark"></div>
</div>
<!-- 文字提示 -->
<div class="drag-tips">
<span>按住左邊按鈕向右拖動完成上方圖像驗(yàn)證</span>
</div>
</div> .drag {
width: 400px;
height: 50px;
background-color: #e3e3e3;
margin-top: 10px;
position: relative;
}
.drag-box {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: aquamarine;
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
}
.drag-tips {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: end;
align-items: center;
width: 95%;
height: 100%;
font-size: 12px;
color: #8a8a8a;
user-select: none;
}
.drag-mark {
width: 8px;
height: 16px;
border-color: #009933;
border-style: solid;
border-width: 0 3px 5px 0;
transform: rotate(45deg);
opacity: 0;
transition: 0.3s;
}動態(tài)滑動
滑動的過程涉及鼠標(biāo)按下、鼠標(biāo)移動、鼠標(biāo)彈起

鼠標(biāo)按下
保存鼠標(biāo)的初始水平值pageX,方便下一步計(jì)算移動值
監(jiān)聽鼠標(biāo)的移動事件
// 鼠標(biāo)按下
const mouseDown = (event) => {
// 獲取鼠標(biāo)坐標(biāo)
preX = event.pageX
// 監(jiān)聽鼠標(biāo)移動
document.addEventListener('mousemove', mouseMove)
}
···鼠標(biāo)移動
- 獲取當(dāng)前的鼠標(biāo)值pageX,和原始值做減法,得到移動值
- 移除監(jiān)聽鼠標(biāo)的移動事件
- 設(shè)置滑塊和被驗(yàn)證區(qū)域塊的移動值
思考:這里使用pageX,clientX都可以實(shí)現(xiàn)相應(yīng)的效果,但是使用offsetX的時(shí)候會出現(xiàn)閃爍的效果,看到很多帖子說使用pointer-events: none解決,我的不可以,留一個(gè)疑問在這里吧:鼠標(biāo)的移動值到底怎么計(jì)算?,等日后參悟透了再來更新。
// 鼠標(biāo)移動
const mouseMove = (event) => {
const { pageX } = event
// 移動距離
const moveX = pageX - preX
// 移動不能超出區(qū)域
if (moveX < 0 || moveX > 350) {
return
}
check.style.transform = `translateX(${moveX}px)`
drag.style.transform = `translateX(${moveX}px)`
}鼠標(biāo)抬起
- 獲取當(dāng)前的鼠標(biāo)值pageX,和原始值做減法,得到移動值
- 判斷移動值是否在有效區(qū)間之內(nèi)
- 在有效區(qū)間,調(diào)用驗(yàn)證通過的回調(diào)函數(shù)
- 不在有效區(qū)間,應(yīng)該給滑塊和被驗(yàn)證區(qū)域塊設(shè)計(jì)回彈動畫的效果
// 鼠標(biāo)抬起
const mouseUp = (event) => {
// 移出移動事件
document.removeEventListener('mousemove', mouseMove)
const { pageX } = event
const moveX = pageX - preX
if (moveX < 278 || moveX > 285) {
.......
} else {
success()
}
}有效驗(yàn)證
有效驗(yàn)證是指驗(yàn)證通過的回調(diào)函數(shù)
// 校驗(yàn)回調(diào)函數(shù)
const success = () => {
console.log('通過校驗(yàn)!')
}動畫處理
對于回彈動畫的處理,首先是css方面,設(shè)計(jì)動畫效果,然后是js方面,滑塊和被驗(yàn)證區(qū)域賦值動畫效果,監(jiān)聽動畫結(jié)束事件,動畫結(jié)束的時(shí)候,滑塊和被驗(yàn)證區(qū)域回到0的位置,清除動畫效果。
/* 回彈動畫 */
@keyframes move {
to {
transform: translateX(0);
}
} if (moveX < 278 || moveX > 285) {
// 沒有在校驗(yàn)區(qū)域 增加回彈動畫
drag.style.animation = 'move 0.5s ease-in-out'
check.style.animation = 'move 0.5s ease-in-out'
// 動畫結(jié)束回調(diào)
const animationEnd = () => {
check.style.transform = `translateX(${0}px)`
drag.style.transform = `translateX(${0}px)`
mark.style.opacity = 0
// 清除動畫
drag.style.animation = ''
check.style.animation = ''
// 取消監(jiān)聽動畫結(jié)束回調(diào)
document.removeEventListener('animationEnd', animationEnd)
}
document.addEventListener('animationend', animationEnd)
}完整代碼
圖片是遠(yuǎn)程服務(wù)器上的,我下載到本地了,點(diǎn)擊上面的底圖鏈接可以獲取到原圖。
<!--
* @Author: Kongjingjing
* @Date: 2023-01-10 15:37:03
* @Description:
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.check {
width: 400px;
height: 300px;
background-image: url(./img/bg.avif);
background-size: 100% 100%;
background-repeat: no-repeat;
position: relative;
filter: brightness(80%);
}
.check::before {
position: absolute;
content: '';
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.5);
top: 100px;
left: 280px;
}
.check-box {
width: 50px;
height: 50px;
position: absolute;
top: 100px;
left: 0;
background-image: inherit;
background-repeat: inherit;
background-size: 400px 300px;
background-position: -280px -100px;
border: 1px solid #fff;
}
.drag {
width: 400px;
height: 50px;
background-color: #e3e3e3;
margin-top: 10px;
position: relative;
}
.drag-box {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: aquamarine;
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
}
.drag-tips {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: end;
align-items: center;
width: 95%;
height: 100%;
font-size: 12px;
color: #8a8a8a;
user-select: none;
}
/* 回彈動畫 */
@keyframes move {
to {
transform: translateX(0);
}
}
.drag-mark {
width: 8px;
height: 16px;
border-color: #009933;
border-style: solid;
border-width: 0 3px 5px 0;
transform: rotate(45deg);
opacity: 0;
transition: 0.3s;
}
</style>
</head>
<body>
<div class="check">
<!-- 驗(yàn)證區(qū)塊通過偽類實(shí)現(xiàn) -->
<!-- 被驗(yàn)證區(qū)塊 -->
<div class="check-box" id="check-box"></div>
</div>
<!-- 拖動條 -->
<div class="drag">
<!-- 滑塊 -->
<div class="drag-box" id="drag-box">
<!-- 對號 -->
<div id="drag-mark" class="drag-mark"></div>
</div>
<!-- 文字提示 -->
<div class="drag-tips">
<span>按住左邊按鈕向右拖動完成上方圖像驗(yàn)證</span>
</div>
</div>
</body>
<script>
// 被驗(yàn)證區(qū)塊
const check = document.getElementById('check-box')
// 滑塊
const drag = document.getElementById('drag-box')
// 對號
const mark = document.getElementById('drag-mark')
let preX = 0
// 鼠標(biāo)按下
const mouseDown = (event) => {
// 獲取鼠標(biāo)坐標(biāo)
preX = event.pageX
// 監(jiān)聽鼠標(biāo)移動
document.addEventListener('mousemove', mouseMove)
}
// 鼠標(biāo)移動
const mouseMove = (event) => {
const { pageX } = event
// 移動距離
const moveX = pageX - preX
// 移動不能超出區(qū)域
if (moveX < 0 || moveX > 350) {
return
}
check.style.transform = `translateX(${moveX}px)`
drag.style.transform = `translateX(${moveX}px)`
}
// 鼠標(biāo)抬起
const mouseUp = (event) => {
// 移出移動事件
document.removeEventListener('mousemove', mouseMove)
const { pageX } = event
const moveX = pageX - preX
if (moveX < 278 || moveX > 285) {
// 沒有在校驗(yàn)區(qū)域 增加回彈動畫
drag.style.animation = 'move 0.5s ease-in-out'
check.style.animation = 'move 0.5s ease-in-out'
// 動畫結(jié)束回調(diào)
const animationEnd = () => {
check.style.transform = `translateX(${0}px)`
drag.style.transform = `translateX(${0}px)`
mark.style.opacity = 0
// 清除動畫
drag.style.animation = ''
check.style.animation = ''
// 取消監(jiān)聽動畫結(jié)束回調(diào)
document.removeEventListener('animationEnd', animationEnd)
}
document.addEventListener('animationend', animationEnd)
} else {
// 對號
mark.style.opacity = 1
success()
}
}
// 校驗(yàn)回調(diào)函數(shù)
const success = () => {
console.log('通過校驗(yàn)!')
}
// 滑塊綁定鼠標(biāo)按下事件
drag.addEventListener('mousedown', mouseDown)
document.addEventListener('mouseup', mouseUp)
</script>
</html>到此這篇關(guān)于JavaScript實(shí)現(xiàn)登錄拼圖驗(yàn)證的示例代碼的文章就介紹到這了,更多相關(guān)JavaScript登錄拼圖驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
three.js 實(shí)現(xiàn)露珠滴落動畫效果的示例代碼
這篇文章主要介紹了three.js 實(shí)現(xiàn)露珠滴落動畫效果的示例代碼,非常不錯(cuò),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
JS為什么說async/await是generator的語法糖詳解
這篇文章主要給大家介紹了關(guān)于JS為什么說async/await是generator的語法糖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
jquery插件jquery.confirm彈出確認(rèn)消息
這篇文章介紹了插件jquery.confirm彈出確認(rèn)消息的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下2015-12-12
JavaScript+Java實(shí)現(xiàn)HTML頁面轉(zhuǎn)為PDF文件保存的方法
借助iText這個(gè)Java庫,我們可以將HTML文件保存為圖片文件進(jìn)而轉(zhuǎn)換成PDF格式,接下來就來具體看下JavaScript+Java實(shí)現(xiàn)HTML頁面轉(zhuǎn)為PDF文件保存的方法2016-05-05

