最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實(shí)現(xiàn)滑塊補(bǔ)圖驗(yàn)證碼效果

 更新時(shí)間:2023年07月16日 11:49:46   作者:寅時(shí)碼  
這篇文章主要給大家介紹了JavaScript如何實(shí)現(xiàn)滑塊補(bǔ)圖驗(yàn)證碼效果,文章通過(guò)代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以參考閱讀下

<div class="container">
    <div class="pic">
        <div class="gap"></div>
        <div class="verify-pic"></div>
    </div>
    <div class="slide">
        <div class="btn"></div>
    </div>
</div>

沒錯(cuò),全部手工繪制,不用任何圖片、svg、字體圖標(biāo)之流

pic為背景圖片,里面放著gap空白塊,verify-pic被拖動(dòng)的驗(yàn)證圖

slide是滑塊,btn是小按鈕

樣式

首先初始化樣式和變量

:root {
    --btn-w: 40px;
    --btn-h: 24px;
    /* 按鈕偽元素 */
    --btn-dot-w: 4px;
    /* 滑塊 */
    --bar-h: 10px;
    /* 背景圖 */
    --pic-w: 640px;
    --pic-h: 390px;
    --pic-src: url(https://i0.hdslb.com/bfs/vc/c13315f4c4195b342fd0d2795fd6c8b090a717bf.jpg);
    --radius: 8px;
}
* {
    margin: 0;
    padding: 0;
}

這幾個(gè)樣式很大眾 沒什么可講的

.container {
    display: flex;
    position: relative;
    height: var(--pic-h);
    width: var(--pic-w);
    flex-flow: column wrap;
    justify-content: space-between;
    padding: 10px;
}
.pic {
    position: relative;
    background: var(--pic-src) no-repeat;
    width: 640px;
    height: 340px;
}
.slide {
    position: relative;
    width: 100%;
    height: var(--bar-h);
    background-color: #999;
    border-radius: 4px;
}
.btn {
    position: absolute;
    left: 0;
    /* (按鈕高度 - 拖動(dòng)條高度) * -1 / 2 */
    top: calc((var(--btn-h) - var(--bar-h)) * -1 / 2);
    width: var(--btn-w);
    height: var(--btn-h);
    background-color: #b5a37e;
    border-radius: 10px;
    cursor: pointer;
}

這個(gè)滑塊按鈕,要想在垂直方向居中,就需要拿按鈕高度 - 滑動(dòng)條高度 / 2

但是為什么要 乘以 -1呢??

因?yàn)?code>DOM坐標(biāo)系是第三象限,負(fù)值為向上

接下來(lái)是里面的倆小薯?xiàng)l了

.btn::after,
.btn::before {
    content: "";
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: calc(var(--btn-w) / 3 - var(--btn-dot-w) / 2);
    height: var(--bar-h);
    width: var(--btn-dot-w);
    background-color: #eee;
}

這里我把整個(gè)滑塊分成三份,所以位置就是滑塊的三分之一,后面的小薯?xiàng)l除以2是為了居中

.btn::before {
    /* 偽元素在按鈕的 2/ 3處 并減去自己的一半用來(lái)居中 */
    left: calc(var(--btn-w) / 3 * 2 - var(--btn-dot-w) / 2);
}

第二個(gè)小薯?xiàng)l就是三分之二的位置即可

至此 樣式完成

操作邏輯 & 效果實(shí)現(xiàn)

const container = document.querySelector('.container'),
    pic = container.querySelector('.pic'), // 大圖
    vPic = pic.querySelector('.verify-pic'), // 拖動(dòng)圖片
    gap = pic.querySelector('.gap'), // 背景圖空白塊
    btn = document.querySelector('.btn'); // 滑動(dòng)條按鈕
const pic_w = getStyle(pic, 'width'),
    pic_h = getStyle(pic, 'height'),
    cont_w = getStyle(container, 'width'),
    cont_h = getStyle(container, 'height'),
    vPic_w = getStyle(vPic, 'width'),
    vPic_h = getStyle(vPic, 'height'),
    btn_w = getStyle(btn, 'width');
const offset = 14;  // 可偏移距離
function getRadom(min, max) {
    return Math.floor(min + Math.random() * (max - min));
}
function getStyle(el, key) {
    return parseInt(getComputedStyle(el)[key]);
}

先獲取DOM以及設(shè)置配置

這里一定不能用offset系列獲取矩形屬性,因?yàn)殡[藏的元素?zé)o法獲取

初始化位置

function setPos() {
    const w = pic_w / 2,
        h = pic_h / 2 - vPic_h;
    // 移動(dòng)空缺元素到右上部分
    const left = getRadom(w, pic_w - vPic_w),
        top = getRadom(0, h);
    gap.style.transform = `translate(${left}px, ${top}px)`;
    vPic.style.backgroundPosition = `${-left}px ${-top}px`;
    return [left, top];
}

把滑塊和圖片 移動(dòng)到右上方隨機(jī)位置

返回值作為最終對(duì)比值

由于left是指元素左邊的距離,所以要減去元素寬度

 let x = 0, // 滑倒最后的值
    moving = false;
btn.addEventListener('mousedown', function (e) {
    moving = true;
    setShow(top, 'block');
});
 btn.addEventListener('mouseup', function () {
    setShow(top, 'none');
});
function setShow(top, flag) {
    vPic.style.display = flag;
    vPic.style.transform = `translateY(${top}px)`;
    btn.style.transform = 'none';
    vPic.style.transform = 'none';
    x = 0;
}

這里的setShow可復(fù)用多次

現(xiàn)在有什么問(wèn)題嗎??

問(wèn)題大著呢,你把mouseup綁在了小按鈕上,當(dāng)你抬起位置不是按鈕,就不能觸發(fā)了

正確做法是綁定在window

接下來(lái)是重點(diǎn),滑動(dòng)事件

 window.addEventListener('mousemove', function (e) {
    if (!moving) {
        return;
    }
    // 圖片位置 = 鼠標(biāo)位置 - 滑動(dòng)條位置 - 按鈕 / 2 ----減去按鈕是居中
    x = e.clientX - container.getBoundingClientRect().left - btn_w / 2;
    btn.style.transform = `translateX(${x}px)`;
    vPic.style.transform = `translate(${x}px, ${top}px)`;
});
 window.addEventListener('mousemove', function (e) {
    if (!moving) {
        return;
    }
    // 圖片位置 = 鼠標(biāo)位置 - 滑動(dòng)條位置 - 按鈕 / 2 ----減去按鈕是居中
    x = e.clientX - container.getBoundingClientRect().left - btn_w / 2;
    btn.style.transform = `translateX(${x}px)`;
    vPic.style.transform = `translate(${x}px, ${top}px)`;
});

這樣基本就實(shí)現(xiàn)了,但是沒有判斷邊界呢,現(xiàn)在可以隨意滑動(dòng)

function judge(x) {
    const { left } = container.getBoundingClientRect();
    return (
        x - left < 0 ||
        x + left > cont_w + left
    );
}
 window.addEventListener('mousemove', function (e) {
    if (!moving || judge(e.clientX)) {
        return;
    }
    // 圖片位置 = 鼠標(biāo)位置 - 滑動(dòng)條位置 - 按鈕 / 2 ----減去按鈕是居中
    x = e.clientX - container.getBoundingClientRect().left - btn_w / 2;
    btn.style.transform = `translateX(${x}px)`;
    vPic.style.transform = `translate(${x}px, ${top}px)`;
});

當(dāng)x軸小于0或者鼠標(biāo)大于圖片寬度時(shí)退出

這時(shí)候給x賦值,鼠標(biāo)抬起時(shí)判斷

 window.addEventListener('mouseup', function () {
    const flag = x > left - offset && x < left + offset;
    moving = false;
    if (flag) {
        cb && cb();
    }
    else {
        setShow(top, 'none');
    }
});

如果成功 執(zhí)行外面的回調(diào)函數(shù) 反之重置位置

現(xiàn)在基本完全實(shí)現(xiàn)

就在我喜出望外之際,我發(fā)現(xiàn)滑動(dòng)一些刁鉆的角度,會(huì)讓鼠標(biāo)屬性改變,變成這樣

cursor: not-allowed;

因?yàn)檫@個(gè)原因,會(huì)擾亂事件

但是我整篇代碼也沒設(shè)置過(guò)

所以我冥思苦想

那一定是事件默認(rèn)行為搞的鬼

所以我給每個(gè)元素阻止了默認(rèn)行為,最終排查發(fā)現(xiàn),是mousedown導(dǎo)致的

 btn.addEventListener('mousedown', function (e) {
    // 不阻止默認(rèn)行為 會(huì)導(dǎo)致鼠標(biāo)屬性變成 `now-allowed`
    e.preventDefault();
    moving = true;
    setShow(top, 'block');
});

以上就是JavaScript實(shí)現(xiàn)滑塊補(bǔ)圖驗(yàn)證碼效果的詳細(xì)內(nèi)容,更多關(guān)于JavaScript滑塊補(bǔ)圖驗(yàn)證碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ExtJs異步無(wú)法向外傳值和賦值的完美解決辦法

    ExtJs異步無(wú)法向外傳值和賦值的完美解決辦法

    這篇文章主要介紹了ExtJs異步無(wú)法向外傳值和賦值的完美解決辦法,需要的朋友可以參考下
    2017-06-06
  • JavaScript中的連續(xù)賦值問(wèn)題實(shí)例分析

    JavaScript中的連續(xù)賦值問(wèn)題實(shí)例分析

    這篇文章主要介紹了JavaScript中的連續(xù)賦值問(wèn)題,結(jié)合實(shí)例形式分析了javascript賦值語(yǔ)句以及連續(xù)賦值操作相關(guān)用法與操作注意事項(xiàng),需要的朋友可以參考下
    2019-07-07
  • JavaScript DOMContentLoaded事件案例詳解

    JavaScript DOMContentLoaded事件案例詳解

    這篇文章主要介紹了JavaScript DOMContentLoaded事件案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • JavaScript學(xué)習(xí)筆記(十)

    JavaScript學(xué)習(xí)筆記(十)

    今天學(xué)習(xí)的是window對(duì)象,還是有點(diǎn)用的。
    2010-01-01
  • 詳談commonjs模塊與es6模塊的區(qū)別

    詳談commonjs模塊與es6模塊的區(qū)別

    下面小編就為大家?guī)?lái)一篇詳談commonjs模塊與es6模塊的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • bootstrap datetimepicker2.3.11時(shí)間插件使用

    bootstrap datetimepicker2.3.11時(shí)間插件使用

    這篇文章主要為大家詳細(xì)介紹了bootstrap datetimepicker2.3.11時(shí)間插件使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • JS綁定事件的3種方法舉例示范(簡(jiǎn)單易懂)

    JS綁定事件的3種方法舉例示范(簡(jiǎn)單易懂)

    在JavaScript的學(xué)習(xí)中我們經(jīng)常會(huì)遇到JavaScript的事件機(jī)制,例如事件綁定、事件監(jiān)聽、事件委托(事件代理)等,這篇文章主要給大家介紹了關(guān)于JS綁定事件的3種方法,需要的朋友可以參考下
    2023-11-11
  • JS+Canvas實(shí)現(xiàn)的俄羅斯方塊游戲完整實(shí)例

    JS+Canvas實(shí)現(xiàn)的俄羅斯方塊游戲完整實(shí)例

    這篇文章主要介紹了JS+Canvas實(shí)現(xiàn)的俄羅斯方塊游戲,結(jié)合完整實(shí)例形式分析了Canvas技術(shù)實(shí)現(xiàn)俄羅斯方塊游戲的步驟、技術(shù)難點(diǎn)與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-12-12
  • 前端引入及使用svg圖片的多種方式大全

    前端引入及使用svg圖片的多種方式大全

    SVG是一種繪圖技術(shù),SVG的全名叫可縮放矢量圖形,這篇文章主要介紹了前端引入及使用svg圖片的多種方式大全,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-11-11
  • JS ES6多行字符串與連接字符串的表示方法

    JS ES6多行字符串與連接字符串的表示方法

    這篇文章主要介紹了JS ES6多行字符串與連接字符串的表示方法,結(jié)合具體實(shí)例形式對(duì)比分析了ES6中的多行字符串與連接字符串的表示方法與相關(guān)操作技巧,需要的朋友可以參考下
    2017-04-04

最新評(píng)論

屏边| 黄梅县| 额尔古纳市| 景洪市| 南充市| 桑植县| 普宁市| 岱山县| 高尔夫| 呼和浩特市| 潜江市| 贡嘎县| 金乡县| 双城市| 沈阳市| 巍山| 哈密市| 会昌县| 万源市| 凉城县| 扶绥县| 彰化县| 旌德县| 临安市| 诸暨市| 探索| 巴中市| 汝州市| 鄯善县| 乃东县| 韶关市| 甘德县| 离岛区| 万全县| 肃北| 扬州市| 新余市| 微博| 白玉县| 高阳县| 灵丘县|