欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

js前端實(shí)現(xiàn)登錄拼圖驗(yàn)證功能

 更新時(shí)間:2023年02月17日 14:26:59   作者:記得抬頭微笑  
行為驗(yàn)證碼通過用戶的操作來完成驗(yàn)證,常見的行為驗(yàn)證碼有拖動(dòng)式和點(diǎn)觸式,下面這篇文章主要給大家介紹了關(guān)于js前端實(shí)現(xiàn)登錄拼圖驗(yàn)證功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

不知各位朋友現(xiàn)在在 web 端進(jìn)行登錄的時(shí)候有沒有注意一個(gè)變化,以前登錄的時(shí)候是直接賬號(hào)密碼通過就可以直接登錄,再后來圖形驗(yàn)證碼,數(shù)字結(jié)果運(yùn)算驗(yàn)證,到現(xiàn)在的拼圖驗(yàn)證。這一系列的轉(zhuǎn)變都是為了防止機(jī)器操作,但對(duì)于我們來說,有億點(diǎn)麻煩,但也沒辦法呀。

今天我們也一起實(shí)現(xiàn)一個(gè)拼圖驗(yàn)證。

核心功能

  •  滑動(dòng)解鎖功能
  •  重置位置功能
  •  滑塊進(jìn)度條功能
  •  結(jié)果提示功能
  •  隨機(jī)生成滑塊位置

實(shí)現(xiàn)原理

這個(gè)的實(shí)現(xiàn)原理并不復(fù)雜,我們只需要一張背景圖作為我們的拼接素材,再單獨(dú)定義一個(gè)盒子并拖拽移動(dòng)它到指定位置就可以完成拼圖驗(yàn)證功能了

實(shí)現(xiàn)前端登錄拼圖驗(yàn)證

搭建框架

我們要實(shí)現(xiàn)這個(gè)功能,我們需要先搭建出來一個(gè)樣式結(jié)構(gòu)出來。

// css
:root {
	 --iWidth: 50px;
	 --iHeight: 50px;
}

.wrapper {
    width: 100%;
    width: 500px;
    margin: 0 auto;
}

.container {
    position: relative;
    width: 500px;
    height: 300px;
    box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.5);
    border-radius: 8px;
    background-image: url("./bg.webp");
    background-size: 100% 100%;
    background-repeat: no-repeat;
}

// html
<div class="wrapper">
   <!-- 容器 -->
   <div class="container"></div>
</div>

我們根據(jù)剛才的樣式結(jié)構(gòu)搭建完成后,它就長下圖這個(gè)樣子

添加被校驗(yàn)區(qū)域及校驗(yàn)區(qū)域

我們需要添加一個(gè)被校驗(yàn)區(qū)域及校驗(yàn)區(qū)域,用來做我們的滑動(dòng)校驗(yàn)
??!在滑動(dòng)區(qū)域中使用 background-position 配合 background-size 根據(jù)校驗(yàn)區(qū)域的大小和位置切出滑動(dòng)區(qū)域的圖

// css
// 被校驗(yàn)區(qū)域樣式
.container-move {
    position: absolute;
    width: var(--iWidth);
    height: var(--iHeight);
    top: 180px;
    left: 0;
    z-index: 3;
    background-size: 500px 300px;
    background-repeat: no-repeat;
    background-image: url("./img/bg.jpg");
    background-position: -180px -200px;
}
// 校驗(yàn)區(qū)域樣式
.container-empty {
    position: absolute;
    width: var(--iWidth);
    height: var(--iHeight);
    top: 180px;
    left: 200px;
    background: #fff;
    z-index: 2;
    opacity: .6;
}
// html
<div class="wrapper">
    <!-- 容器 -->
    <div class="container">
    	<!-- 被校驗(yàn)區(qū)域 -->
        <div class="container-move"></div>
        <!-- 校驗(yàn)區(qū)域 -->
        <div class="container-empty"></div>
    </div>
</div>

效果圖

添加滑塊、滑塊背景、拖動(dòng)條、提示文字

拖動(dòng)條來控制滑塊移動(dòng)的最大距離
滑塊來控制被校驗(yàn)區(qū)域的移動(dòng)距離
提示文字是提示用戶這里可以操作解鎖

拖動(dòng)條內(nèi)的滑塊、滑塊背景、提示文字都對(duì)拖動(dòng)條進(jìn)行絕對(duì)定位
主要是為了控制他們的層級(jí),提示文字 < 滑塊背景 < 滑塊

我們添加滑塊、滑塊背景、拖動(dòng)條、提示文字

// css
/* 拖動(dòng)條樣式 */
.slider-control {
    width: 500px;
    height: 50px;
    margin-top: 20px;
    border-radius: 4px;
    position: relative;
    overflow: hidden;
    background: #f2f2f2;
    box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
}

/* 滑塊 */
.slider {
    width: var(--iWidth);
    height: var(--iHeight);
    position: absolute;
    left: 0;
    top: 0;
    background: skyblue;
    border-radius: 4px;
    text-align: center;
    line-height: var(--iHeight);
    transition: all;
    user-select: none;
    z-index: 3;
}

/* 滑塊背景 */
.slider-shadow {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 50px;
    background: #fff;
    z-index: 2;
}

/* 提示文案 */
.slider-info {
    text-align: center;
    color: rgba(102, 102, 102, 1);
    margin: 0;
    line-height: 50px;
}
// html
<div class="wrapper">
    <!-- 控制容器 -->
    <div class="slider-control">
    	// 提示文字
        <p class="slider-info">按住左邊按鈕向右拖動(dòng)完成上方圖像驗(yàn)證</p>
         // 滑塊
        <div class="slider">>></div>
        // 滑塊背景
        <div class="slider-shadow"></div>
    </div>
</div>

效果圖如下

添加交互

到這里拼圖驗(yàn)證的樣式結(jié)構(gòu)已經(jīng)完成了,接下來我們需要對(duì)相關(guān)的元素添加交互事件

讓滑塊可以在拖動(dòng)條內(nèi)隨意拖拽

// 我太懶了,不想寫那么一大堆,這里封裝個(gè)用 class 來獲取實(shí)例的函數(shù)
function getElement(elName) {
   return document.getElementsByClassName(elName)[0]
}

// 獲取實(shí)例
let sliderBox = getElement('slider'); // 滑動(dòng)的塊
let sliderShadow = getElement('slider-shadow'); // 滑動(dòng)背景

let container = getElement("container"); // 容器的實(shí)例
let sliderMove = getElement("container-move"); // 解鎖的塊

let containerWidth = container.clientWidth; // 獲取容器的可視區(qū)寬度
let sliderMoveWidth = sliderMove.clientWidth; // 被校驗(yàn)區(qū)域的可視區(qū)寬度
        
let maxDistance = (containerWidth - sliderMoveWidth); // 根據(jù)容器和被校驗(yàn)區(qū)域的大小限制滑塊移動(dòng)最大的距離

/**
* 監(jiān)聽鼠標(biāo)在sliderBox(滑動(dòng)塊)按下時(shí) mousedowm, 并根據(jù)可視區(qū)左邊的距離減去鼠標(biāo)按下的距離, 獲取到實(shí)際
* document的onmouseMove和mouseup事件,
* 獲取鼠標(biāo)滑動(dòng)的位置
*/
sliderBox.onmousedown = function (moveStart) {
   // console.log("?? ~ file: index.html ~ line 94 ~ moveStart", moveStart)
   let left = moveStart.clientX - sliderBox.offsetLeft; // 獲取按下時(shí)元素距離可視區(qū)左邊的位置 - 鼠標(biāo)按下時(shí)的位置, 獲取到鼠標(biāo)距離元素邊緣的位置
   let lefta // 記錄移動(dòng)的距離
   // 鼠標(biāo)按下持續(xù)移動(dòng)中
   document.onmousemove = function (moveTo) {
       // 如果不減去 left 那么就會(huì)導(dǎo)致鼠標(biāo)一直在移動(dòng)元素的左邊框上, 也就會(huì)出現(xiàn)元素不跟著鼠標(biāo)走的問題, 有偏差
       lefta = moveTo.clientX - left; // 元素移動(dòng)的距離
       // 限制元素的移動(dòng)距離,不能小于0, 或者大于最大寬度 - 元素本身的距離, 否則就初始化位置
       if (lefta < 0) {
           lefta = 0;
       } else if (maxDistance < lefta) {
           lefta = maxDistance;
       }
       sliderBox.style.left = lefta + 'px';
       // 因?yàn)榛瑝K加了圓角的功能,所以要在這里加4px,讓滑塊剛好壓住滑塊背景,不加的話,放大的時(shí)候會(huì)比較突兀
       sliderShadow.style.width = (lefta + 4) + 'px';
   }

   // 鼠標(biāo)移動(dòng)結(jié)束
   document.onmouseup = function (moveEnd) {
       // 解除document身上綁定的事件, 不讓事件一直觸發(fā)
       document.onmousemove = null;
       document.onmouseup = null;
       // 重置位置
       sliderBox.style.left = 0 + 'px'
       sliderShadow.style.width = 0 + 'px'
   }
}

通過我們上述代碼實(shí)現(xiàn)的效果圖,可以看到滑塊可以在拖動(dòng)條內(nèi)隨意拖動(dòng)了,且滑塊、滑塊背景、文字的層級(jí)關(guān)系也處理好了

聯(lián)動(dòng)被校驗(yàn)區(qū)域

我們?cè)谏鲜鰞?nèi)容中已經(jīng)實(shí)現(xiàn)了滑塊的自由拖拽,接下來就要聯(lián)動(dòng)被校驗(yàn)區(qū)域的滑動(dòng)位置進(jìn)行校驗(yàn)

// 獲取實(shí)例以及定義常量
let faultSize = 10; // 滑動(dòng)距離的容錯(cuò)處理, 滑動(dòng)距離- 10, +10 都可解鎖
// 事件處理
sliderBox.onmousedown = function (moveStart) {
    let left = moveStart.clientX - sliderBox.offsetLeft; // 獲取按下時(shí)元素距離可視區(qū)左邊的位置 - 鼠標(biāo)按下時(shí)的位置, 獲取到鼠標(biāo)距離元素邊緣的位置
    let lefta // 記錄移動(dòng)的距離
    // 鼠標(biāo)按下持續(xù)移動(dòng)中
    document.onmousemove = function (moveTo) {
        // 如果不減去 left 那么就會(huì)導(dǎo)致鼠標(biāo)一直在移動(dòng)元素的左邊框上, 也就會(huì)出現(xiàn)元素不跟著鼠標(biāo)走的問題, 有偏差
        lefta = moveTo.clientX - left; // 元素移動(dòng)的距離
        sliderMove.style.left = lefta + 'px'
    }

    // 鼠標(biāo)移動(dòng)結(jié)束
    document.onmouseup = function (moveEnd) {
        // 判斷滑動(dòng)距離是否相同,這里的滑動(dòng)距離允許10px的容錯(cuò),所以在當(dāng)被校驗(yàn)區(qū)域大于小于校驗(yàn)區(qū)域10px都可以校驗(yàn)通過
        if (lefta >= movePointer - faultSize && lefta <= movePointer + faultSize) {
            success(true)
        } else {
            success(false)
        }
        init()
        // 重置位置
        sliderBox.style.left = 0 + 'px'
        sliderMove.style.left = 0 + 'px'
        sliderShadow.style.width = 0 + 'px';
        infomation.innerText = ''
    }
}

function success(valid) {
    let text = valid ? '成功' : "失敗"
    alert(`解鎖${text}`)
}

通過我們的上述代碼就已經(jīng)實(shí)現(xiàn)了拼圖驗(yàn)證的功能,我們有一個(gè)隨機(jī)生成校驗(yàn)位置的功能沒有實(shí)現(xiàn),下面我們一起來實(shí)現(xiàn)一下吧

隨機(jī)生成校驗(yàn)位置

在我們登錄平臺(tái)系統(tǒng)的時(shí)候,當(dāng)我們的拼圖沒有移動(dòng)到指定位置或移動(dòng)錯(cuò)誤的時(shí)候,都是需要重新生成校驗(yàn)位置的,所以拼圖刷新功能還是很有必要的,下面我們就一起來實(shí)現(xiàn)一下吧。

// css
/* 重置 */
.container-reset {
   position: absolute;
   top: 0;
   right: 10px;
   cursor: pointer;
   user-select: none;
   z-index: 1;
   color:#fff;
}
// html
<div class="wrapper">
<!-- 解鎖容器 -->
<div class="container">
   <div class="container-reset">刷新</div>
</div>
</div>
// js

// 獲取實(shí)例
let containerReset = getElement('container-reset'); // 刷新按鈕實(shí)例

// 初始化位置
init()
// 刷新拼圖位置
containerReset.onclick = function () {
    init()
}
/**
 * 隨機(jī)生成空白的位置, 并指定解鎖塊的高度
 *  */
function init() {
    const moveTop = Math.floor(Math.random() * 90); // 校驗(yàn)區(qū)域隨機(jī)生成的 top 高度
    const moveLeft = Math.floor(Math.random() * (270 - 60) + 60); // 校驗(yàn)區(qū)域隨機(jī)生成的 left 距離

    movePointer = moveLeft // 重置校驗(yàn)區(qū)域解鎖的位置

    sliderMove.style.top = moveTop + 'px'; // 初始化被校驗(yàn)區(qū)域位置

    containerEmpty.style.top = moveTop + 'px'; // 初始化校驗(yàn)區(qū)域
    containerEmpty.style.left = moveLeft + 'px'; // 初始化校驗(yàn)區(qū)域

    sliderShadow.style.width = 0 + 'px'; // 重置拖拖動(dòng)條陰影位置

    sliderMove.style.backgroundPosition = `-${moveLeft}px  -${moveTop}px`; // 裁剪被校驗(yàn)區(qū)域上的切圖
}

到這里看一下我們都一起實(shí)現(xiàn)文章開頭說的這些功能,是不是也沒有想象中的那么難?

  •  滑動(dòng)解鎖功能
  •  重置位置功能
  •  滑塊進(jìn)度條功能
  •  結(jié)果提示功能
  •  隨機(jī)生成滑塊位置

完整代碼

<!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>滑動(dòng)驗(yàn)證碼</title>
    <style>
        :root {
            --iWidth: 50px;
            --iHeight: 50px;
        }

        .wrapper {
            width: 100%;
            width: 500px;
            margin: 0 auto;
        }

        /* 容器 */
        .container {
            position: relative;
            width: 500px;
            height: 300px;
            box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
            border-radius: 8px;
            background-image: url("./img/bg.jpg");
            background-size: 100% 100%;
            background-repeat: no-repeat;
        }

        /* 被校驗(yàn)區(qū)域 */
        .container-move {
            position: absolute;
            width: var(--iWidth);
            height: var(--iHeight);
            top: 180px;
            left: 0;
            z-index: 3;
            background-size: 500px 300px;
            background-repeat: no-repeat;
            background-image: url("./img/bg.jpg");
            background-position: -180px -200px;
        }

        /* 校驗(yàn)區(qū)域 */
        .container-empty {
            position: absolute;
            width: var(--iWidth);
            height: var(--iHeight);
            top: 180px;
            left: 200px;
            background: #fff;
            z-index: 2;
            opacity: .6;
        }

        /* 重置 */
        .container-reset {
            position: absolute;
            top: 0;
            right: 10px;
            cursor: pointer;
            user-select: none;
            z-index: 1;
            color:#fff;
        }

        /* 拖動(dòng)條樣式 */
        .slider-control {
            width: 500px;
            height: 50px;
            margin-top: 20px;
            border-radius: 4px;
            position: relative;
            overflow: hidden;
            background: #f2f2f2;
            box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
        }

        /* 滑塊 */
        .slider {
            width: var(--iWidth);
            height: var(--iHeight);
            position: absolute;
            left: 0;
            top: 0;
            background: skyblue;
            border-radius: 4px;
            text-align: center;
            line-height: var(--iHeight);
            transition: all;
            user-select: none;
            z-index: 3;
        }

        /* 滑塊背景 */
        .slider-shadow {
            position: absolute;
            left: 0;
            top: 0;
            width: 0;
            height: 50px;
            background: #fff;
            z-index: 2;
        }

        /* 提示文案 */
        .slider-info {
            text-align: center;
            color: rgba(102, 102, 102, 1);
            margin: 0;
            line-height: 50px;
            user-select: none;
        }
    </style>
</head>

<body>
    <div class="wrapper">
        <!-- 解鎖容器 -->
        <div class="container">
            <div class="container-move"></div>
            <div class="container-empty"></div>
            <div class="container-reset">刷新</div>
        </div>
        <!-- 控制容器 -->
        <div class="slider-control">
            <p class="slider-info">按住左邊按鈕向右拖動(dòng)完成上方圖像驗(yàn)證</p>
            <div class="slider">>></div>
            <div class="slider-shadow"></div>
        </div>
        <p class="infomation"></p>
    </div>


    <script>
        let sliderBox = getElement('slider'); // 滑動(dòng)的塊

        let sliderShadow = getElement('slider-shadow'); // 滑動(dòng)的陰影
        let container = getElement("container"); // 最外層的盒子
        let sliderMove = getElement("container-move"); // 解鎖的塊
        let containerEmpty = getElement("container-empty"); // 解鎖的位置

        let infomation = getElement('infomation'); // 解鎖提示
        let containerReset = getElement('container-reset'); // 重置功能

        let containerWidth = container.clientWidth; // 獲取背景圖的大小
        let sliderMoveWidth = sliderMove.clientWidth; // 解鎖的塊的大小

        let movePointer = containerEmpty.offsetLeft // 解鎖的位置

        let maxDistance = (containerWidth - sliderMoveWidth); // 根據(jù)背景和解鎖塊的寬度限制滑塊移動(dòng)最大的距離

        let faultSize = 10; // 滑動(dòng)距離的容錯(cuò)處理, 滑動(dòng)距離- 10, +10 都可解鎖

        init()

        containerReset.onclick = function () {
            init()
        }

        /**
         * 監(jiān)聽鼠標(biāo)在sliderBox(滑動(dòng)塊)按下時(shí) mousedowm, 并根據(jù)可視區(qū)左邊的距離減去鼠標(biāo)按下的距離, 獲取到實(shí)際
         * document的onmouseMove和mouseup事件,
         * 獲取鼠標(biāo)滑動(dòng)的位置
        */
        sliderBox.onmousedown = function (moveStart) {
            let left = moveStart.clientX - sliderBox.offsetLeft; // 獲取按下時(shí)元素距離可視區(qū)左邊的位置 - 鼠標(biāo)按下時(shí)的位置, 獲取到鼠標(biāo)距離元素邊緣的位置
            let lefta // 記錄移動(dòng)的距離
            // 鼠標(biāo)按下持續(xù)移動(dòng)中
            document.onmousemove = function (moveTo) {
                // 如果不減去 left 那么就會(huì)導(dǎo)致鼠標(biāo)一直在移動(dòng)元素的左邊框上, 也就會(huì)出現(xiàn)元素不跟著鼠標(biāo)走的問題, 有偏差
                lefta = moveTo.clientX - left; // 元素移動(dòng)的距離
                // 限制元素的移動(dòng)距離,不能小于0, 或者大于最大寬度 - 元素本身的距離, 否則就初始化位置
                if (lefta < 0) {
                    lefta = 0;
                } else if (maxDistance < lefta) {
                    lefta = maxDistance;
                }
                sliderBox.style.left = lefta + 'px'
                sliderMove.style.left = lefta + 'px'
                // 因?yàn)榛瑝K加了圓角的功能,所以要在這里加4px,讓滑塊剛好壓住滑塊背景,不加的話,放大的時(shí)候會(huì)比較突兀
                sliderShadow.style.width = (lefta + 4) + 'px';
            }

            // 鼠標(biāo)移動(dòng)結(jié)束
            document.onmouseup = function (moveEnd) {
                // 解除document身上綁定的事件, 不讓事件一直觸發(fā)
                document.onmousemove = null;
                document.onmouseup = null;
                // 判斷滑動(dòng)距離是否相同,這里的滑動(dòng)距離允許10px的容錯(cuò),所以在當(dāng)被校驗(yàn)區(qū)域大于小于校驗(yàn)區(qū)域10px都可以校驗(yàn)通過
                if (lefta >= movePointer - faultSize && lefta <= movePointer + faultSize) {
                    success(true)
                } else {
                    success(false)
                }
                init()
                // 重置位置
                sliderBox.style.left = 0 + 'px'
                sliderMove.style.left = 0 + 'px'
                sliderShadow.style.width = 0 + 'px';
                infomation.innerText = ''
            }
        }


        function success(valid) {
            let text = valid ? '成功' : "失敗"
            infomation.innerText = `解鎖${text}`
            alert(`解鎖${text}`)
        }

        /**
         * 隨機(jī)生成空白的位置, 并指定解鎖塊的高度
         *  */
        function init() {
            const moveTop = Math.floor(Math.random() * 90); // 滑塊隨機(jī)生成的高度
            const moveLeft = Math.floor(Math.random() * (270 - 60) + 60); // 滑塊隨機(jī)生成的left距離

            movePointer = moveLeft // 重置滑塊解鎖的位置

            sliderMove.style.top = moveTop + 'px'; // 初始化滑塊位置

            containerEmpty.style.top = moveTop + 'px'; // 初始化解鎖區(qū)域
            containerEmpty.style.left = moveLeft + 'px';

            sliderShadow.style.width = 0 + 'px';

            sliderMove.style.backgroundPosition = `-${moveLeft}px  -${moveTop}px`
        }

        function getElement(elName) {
            return document.getElementsByClassName(elName)[0]
        }
    </script>
</body>

</html>

本篇前端實(shí)現(xiàn)登錄拼圖驗(yàn)證就到此結(jié)束了,這個(gè)功能一般都是在登錄的時(shí)候用的。文章中的案例可以正常使用哦 ~

總結(jié)

到此這篇關(guān)于js前端實(shí)現(xiàn)登錄拼圖驗(yàn)證功能的文章就介紹到這了,更多相關(guān)前端登錄拼圖驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論