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è)對(duì)號(hào)是通過border-width實(shí)現(xiàn)的,感覺很妙呀!
<!-- 拖動(dòng)條 --> <div class="drag"> <!-- 滑塊 --> <div class="drag-box" id="drag-box"> <!-- 對(duì)號(hào) --> <div id="drag-mark" class="drag-mark"></div> </div> <!-- 文字提示 --> <div class="drag-tips"> <span>按住左邊按鈕向右拖動(dòng)完成上方圖像驗(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; }
動(dòng)態(tài)滑動(dòng)
滑動(dòng)的過程涉及鼠標(biāo)按下、鼠標(biāo)移動(dòng)、鼠標(biāo)彈起
鼠標(biāo)按下
保存鼠標(biāo)的初始水平值pageX,方便下一步計(jì)算移動(dòng)值
監(jiān)聽鼠標(biāo)的移動(dòng)事件
// 鼠標(biāo)按下 const mouseDown = (event) => { // 獲取鼠標(biāo)坐標(biāo) preX = event.pageX // 監(jiān)聽鼠標(biāo)移動(dòng) document.addEventListener('mousemove', mouseMove) } ···
鼠標(biāo)移動(dòng)
- 獲取當(dāng)前的鼠標(biāo)值pageX,和原始值做減法,得到移動(dòng)值
- 移除監(jiān)聽鼠標(biāo)的移動(dòng)事件
- 設(shè)置滑塊和被驗(yàn)證區(qū)域塊的移動(dòng)值
思考:這里使用pageX,clientX都可以實(shí)現(xiàn)相應(yīng)的效果,但是使用offsetX的時(shí)候會(huì)出現(xiàn)閃爍的效果,看到很多帖子說使用pointer-events: none
解決,我的不可以,留一個(gè)疑問在這里吧:鼠標(biāo)的移動(dòng)值到底怎么計(jì)算?,等日后參悟透了再來更新。
// 鼠標(biāo)移動(dòng) const mouseMove = (event) => { const { pageX } = event // 移動(dòng)距離 const moveX = pageX - preX // 移動(dòng)不能超出區(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,和原始值做減法,得到移動(dòng)值
- 判斷移動(dòng)值是否在有效區(qū)間之內(nèi)
- 在有效區(qū)間,調(diào)用驗(yàn)證通過的回調(diào)函數(shù)
- 不在有效區(qū)間,應(yīng)該給滑塊和被驗(yàn)證區(qū)域塊設(shè)計(jì)回彈動(dòng)畫的效果
// 鼠標(biāo)抬起 const mouseUp = (event) => { // 移出移動(dòng)事件 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)!') }
動(dòng)畫處理
對(duì)于回彈動(dòng)畫的處理,首先是css方面,設(shè)計(jì)動(dòng)畫效果,然后是js方面,滑塊和被驗(yàn)證區(qū)域賦值動(dòng)畫效果,監(jiān)聽動(dòng)畫結(jié)束事件,動(dòng)畫結(jié)束的時(shí)候,滑塊和被驗(yàn)證區(qū)域回到0的位置,清除動(dòng)畫效果。
/* 回彈動(dòng)畫 */ @keyframes move { to { transform: translateX(0); } }
if (moveX < 278 || moveX > 285) { // 沒有在校驗(yàn)區(qū)域 增加回彈動(dòng)畫 drag.style.animation = 'move 0.5s ease-in-out' check.style.animation = 'move 0.5s ease-in-out' // 動(dòng)畫結(jié)束回調(diào) const animationEnd = () => { check.style.transform = `translateX(${0}px)` drag.style.transform = `translateX(${0}px)` mark.style.opacity = 0 // 清除動(dòng)畫 drag.style.animation = '' check.style.animation = '' // 取消監(jiān)聽動(dòng)畫結(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; } /* 回彈動(dòng)畫 */ @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> <!-- 拖動(dòng)條 --> <div class="drag"> <!-- 滑塊 --> <div class="drag-box" id="drag-box"> <!-- 對(duì)號(hào) --> <div id="drag-mark" class="drag-mark"></div> </div> <!-- 文字提示 --> <div class="drag-tips"> <span>按住左邊按鈕向右拖動(dòng)完成上方圖像驗(yàn)證</span> </div> </div> </body> <script> // 被驗(yàn)證區(qū)塊 const check = document.getElementById('check-box') // 滑塊 const drag = document.getElementById('drag-box') // 對(duì)號(hào) 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)移動(dòng) document.addEventListener('mousemove', mouseMove) } // 鼠標(biāo)移動(dòng) const mouseMove = (event) => { const { pageX } = event // 移動(dòng)距離 const moveX = pageX - preX // 移動(dòng)不能超出區(qū)域 if (moveX < 0 || moveX > 350) { return } check.style.transform = `translateX(${moveX}px)` drag.style.transform = `translateX(${moveX}px)` } // 鼠標(biāo)抬起 const mouseUp = (event) => { // 移出移動(dòng)事件 document.removeEventListener('mousemove', mouseMove) const { pageX } = event const moveX = pageX - preX if (moveX < 278 || moveX > 285) { // 沒有在校驗(yàn)區(qū)域 增加回彈動(dòng)畫 drag.style.animation = 'move 0.5s ease-in-out' check.style.animation = 'move 0.5s ease-in-out' // 動(dòng)畫結(jié)束回調(diào) const animationEnd = () => { check.style.transform = `translateX(${0}px)` drag.style.transform = `translateX(${0}px)` mark.style.opacity = 0 // 清除動(dòng)畫 drag.style.animation = '' check.style.animation = '' // 取消監(jiān)聽動(dòng)畫結(jié)束回調(diào) document.removeEventListener('animationEnd', animationEnd) } document.addEventListener('animationend', animationEnd) } else { // 對(duì)號(hào) 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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
three.js 實(shí)現(xiàn)露珠滴落動(dòng)畫效果的示例代碼
這篇文章主要介紹了three.js 實(shí)現(xiàn)露珠滴落動(dòng)畫效果的示例代碼,非常不錯(cuò),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03JS為什么說async/await是generator的語法糖詳解
這篇文章主要給大家介紹了關(guān)于JS為什么說async/await是generator的語法糖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07jquery插件jquery.confirm彈出確認(rèn)消息
這篇文章介紹了插件jquery.confirm彈出確認(rèn)消息的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下2015-12-12JS實(shí)現(xiàn)的碰撞檢測與周期移動(dòng)完整示例
這篇文章主要介紹了JS實(shí)現(xiàn)的碰撞檢測與周期移動(dòng),結(jié)合完整實(shí)例形式分析了javascript結(jié)合時(shí)間函數(shù)的頁面元素屬性動(dòng)態(tài)操作及事件響應(yīng)相關(guān)使用技巧,需要的朋友可以參考下2019-09-09JavaScript+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