【JS】滑动验证实现

·功能需求:(图片可根据自行更换)

1.、右侧标签的位置是随机生成,左侧标签和右侧标签的垂直位置是一致的,

2、通过滑动条控制左侧标签与右侧标签重叠(误差控制在2px)表示验证通过,

3、否则验证失败,重新生成随机位置。

一、效果展示

·效果示例图

二、代码区域

2.1 核心代码区域

鼠标按下滑块时,需要获取鼠标在当前页面的坐标,以及判断滑块的移动范围。

// 鼠标按下滑块
        liElement.onmousedown = function (e) {
            rx = e.pageX - wrap.offsetLeft;
            var mx = containerWidth - liElement.offsetWidth;
            isDown = true;//鼠标按下
            // 鼠标在页面移动
            document.onmousemove = function (event) {
                // 计算出滑块的位置(鼠标在页面的坐标 减去  鼠标在滑块的坐标)
                // x = event.pageX - rx - liElement.offsetWidth  + cx;
                x = event.pageX - rx - liElement.offsetWidth;
                // 判断是否超出滑动范围
                if (x <= 0) x = 0;
                if (x >= mx) x = mx;
                // 设置滑块的位置
                liElement.style["left"] = x + "px";
                divElement.style["width"] = x + "px";

                // 设置红色标签的位置
                red_x = red_cur_X + x;
                console.log("red_x:", red_x);
                if (red_x >= (containerWidth - red.offsetWidth)) red_x = containerWidth - red.offsetWidth
                red.style["left"] = red_x + "px";
            }
        }

鼠标在页面松开时,判断滑块是否到达缺口的检测范围内,误差为2px。

// 鼠标在页面松开
        document.onmouseup = function () {
            // 解绑鼠标移动事件
            document.onmousemove = null;
            // cx = x;

            //判断鼠标是否按下滑块
            if (isDown) {
                // 检查红色和绿色标签的位置
                // console.log("红色盒子的X位置:",red_x);
                // console.log("绿色盒子的X位置:",green_x);

                // 判断是否验证通过
                if (red_x <= (green_x + 2) && red_x >= (green_x - 2)) {
                    alert("验证成功!")
                    console.log("验证通过!");
                }
                else {
                    console.log("验证失败~~");
                    alert("验证失败~~");
                    // 刷新页面
                    window.location.reload();
                }
            }
            // 重置布尔值
            isDown = false;
        }

2.2详细代码区域

2.2.1css代码
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
        }

        .wrap {
            width: 600px;
            height: 460px;
            margin: 50px;
        }

        .wrap-container {
            width: 600px;
            height: 400px;
            background-color: #ccc;
            /* 相对定位 */
            position: relative;
        }

        .wrap-container .bg {
            width: 600px;
            height: 400px;
            background-image: url(./images/1.jpg);
            background-size: cover;
        }

        .wrap-container .box {
            width: 80px;
            height: 80px;
            position: absolute;
            top: 50px;
            box-shadow: 0px 0px 2px #fff;
        }

        .wrap-container .red {
            background-color: red;
            left: 0;
            /* 层级 */
            z-index: 1000;
            background-repeat: no-repeat;
        }

        .wrap-container .green {
            background-color: rgba(255, 255, 255, .5);
            left: 200px;
        }

        .wrap-side {
            width: 598px;
            height: 48px;
            background-color: #fff;
            margin-top: 10px;
            position: relative;
            border: 1px solid #ccc;
        }

        .wrap-side p {
            color: #666;
            text-align: center;
            line-height: 50px;
            /* 禁止选择文本 */
            user-select: none;
        }

        .wrap-side ul {
            position: absolute;
            top: 0;
            left: 0;
            width: 600px;
            height: 50px;
        }

        .wrap-side ul li {
            width: 50px;
            height: 50px;
            background-color: #1890FF;
            cursor: move;
            position: absolute;
            left: 0px;
            top: 0;
            text-align: center;
            line-height: 50px;
        }

        .wrap-side ul li::before {
            content: "";
            display: inline-block;
            width: 10px;
            height: 10px;
            border-right: 2px solid #fff;
            border-top: 2px solid #fff;
            /* 旋转属性 */
            transform: rotate(45deg);
            /* 垂直对齐 */
            vertical-align: middle;
        }

        .wrap-side div {
            width: 0px;
            height: 50px;
            background-color: rgba(0, 191, 255, .5);
            position: absolute;
            left: 0px;
            top: 0;
        }
    </style>
2.2.2 html代码
<div class="wrap">
        <div class="wrap-container">
            <div class="bg" style="background-image: url(./images/1.jpg);"></div>
            <div class="box red"></div>
            <div class="box green"></div>
        </div>
        <div class="wrap-side">
            <p>向右滑动</p>
            <!-- 滑动条 -->
            <ul>
                <li></li>
            </ul>
            <!-- 滑动经过的地方设置背景 -->
            <div></div>
        </div>
    </div>
2.2.3 JS代码

存放照片的数组中的照片路径用户可根据自己存放的路径进行修改(建议选择尺寸一致的照片)。

// 1. 获取页面相关的元素
        var wrap = document.querySelector(".wrap");
        var wrapContainer = document.querySelector(".wrap-container");
        var bg = document.querySelector(".wrap-container .bg");
        var red = document.querySelector(".wrap-container .red");
        var green = document.querySelector(".wrap-container .green");
        var liElement = document.querySelector(".wrap-side ul li");
        var divElement = document.querySelector(".wrap-side div");

        // 采用数组记录图片路径
        var arr = [
            '.\/images\/1.jpg',
            '.\/images\/2.jpeg',
            '.\/images\/3.jpg',
            '.\/images\/4.jpg',
            '.\/images\/5.jpg',
            '.\/images\/6.jpeg',
        ]

        // 2. 封装函数 生成随机数
        var getRdNum = function (min, max) {
            // 获取指定范围的随机数 
            return Math.floor(Math.random() * (max - min) + min);
        }

        // 3. 记录滑动所需的数据
        // 记录.wrap标签的在页面的位置
        var oLeft = wrap.offsetLeft;
        var oTop = wrap.offsetTop;

        // 记录.wrap-container标签的尺寸
        var containerWidth = wrapContainer.offsetWidth;
        var containerHeight = wrapContainer.offsetHeight;

        // 记录绿色标签和红色标签的位置范围
        // var min_slide_X = 0;
        var min_slide_X = containerWidth / 2;
        var max_silde_X = containerWidth - green.offsetWidth;
        var min_slide_Y = 0;
        var max_silde_Y = containerHeight - green.offsetHeight;

        // 记录红色标签可滑动的范围
        var red_slide_X = containerWidth - red.offsetWidth;

        // 封装函数 获取绿色标签的随机的位置
        var getPos = function () {
            // 返回坐标
            return {
                x: getRdNum(min_slide_X, max_silde_X),
                y: getRdNum(min_slide_Y, max_silde_Y),
                x0: getRdNum(0, min_slide_X - red.offsetWidth)// 红色标签的水平位置
            }
        }
        // 封装函数 设置绿色/红色盒子的位置
        var setPos = function () {
            var point = getPos();
            green.style['left'] = point.x + "px";
            green.style['top'] = point.y + "px";
            red.style['left'] = point.x0 + "px";
            red.style['top'] = point.y + "px";

            // 选择.green标签区域对应的图片
            // 随机的索引值
            var index = Math.floor(Math.random() * arr.length);
            var path = `url(${arr[index]})`;
            // 设置背景图
            bg.style['backgroundImage'] = path;
            red.style['backgroundImage'] = path;
            // 计算出截取的部分图片
            var posX = point.x;
            var posY = point.y;
            // 设置.red标签的背景图位置
            red.style['backgroundPosition'] = `-${posX}px -${posY}px`;
        }
        setPos();

        // 记录红色标签当前的位置
        var red_cur_X = parseInt(getComputedStyle(red)['left']);

        // 设置滑动条
        // 记录滑块的位置
        var x = 0;

        // 记录鼠标在滑块中的位置
        var rx = 0;

        // 记录滑块当前位置
        // var cx = 0;

        // 记录红色盒子的位置(和绿色盒子的位置进行判断)
        var red_x = 0;
        // 记录绿色盒子的位置(获取初始值即可)
        var green_x = parseInt(getComputedStyle(green)['left']);

        // 定义布尔值 判断鼠标是否按下
        var isDown = false;

        // 鼠标按下滑块
        liElement.onmousedown = function (e) {
            rx = e.pageX - wrap.offsetLeft;
            var mx = containerWidth - liElement.offsetWidth;
            isDown = true;//鼠标按下
            // 鼠标在页面移动
            document.onmousemove = function (event) {
                // 计算出滑块的位置(鼠标在页面的坐标 减去  鼠标在滑块的坐标)
                // x = event.pageX - rx - liElement.offsetWidth  + cx;
                x = event.pageX - rx - liElement.offsetWidth;
                // 判断是否超出滑动范围
                if (x <= 0) x = 0;
                if (x >= mx) x = mx;
                // 设置滑块的位置
                liElement.style["left"] = x + "px";
                divElement.style["width"] = x + "px";

                // 设置红色标签的位置
                red_x = red_cur_X + x;
                console.log("red_x:", red_x);
                if (red_x >= (containerWidth - red.offsetWidth)) red_x = containerWidth - red.offsetWidth
                red.style["left"] = red_x + "px";


            }
        }
        // 鼠标在页面松开
        document.onmouseup = function () {
            // 解绑鼠标移动事件
            document.onmousemove = null;
            // cx = x;

            //判断鼠标是否按下滑块
            if (isDown) {
                // 检查红色和绿色标签的位置
                // console.log("红色盒子的X位置:",red_x);
                // console.log("绿色盒子的X位置:",green_x);

                // 判断是否验证通过
                if (red_x <= (green_x + 2) && red_x >= (green_x - 2)) {
                    alert("验证成功!")
                    console.log("验证通过!");
                }
                else {
                    console.log("验证失败~~");
                    alert("验证失败~~");
                    // 刷新页面
                    window.location.reload();
                }
            }

            // 重置布尔值
            isDown = false;
        }

三、个人总结

        实现该功能运用了鼠标点击事件及鼠标松开事件,其中需要滤清如何获取滑块在照片中的位置以及如何将底部滑块与左侧滑块的坐标相联系,这是此案例的关键所在。


注: 博主每天记录自己所学,如有写的不好之处,希望您能不吝赐教,给我一些关于这个项目的意见和建议。各位的宝贵意见将对我产生深远的影响,我将认真倾听并尽力改进。谢谢各位~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/482163.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓手机系统跳过app启动广告软件

跳过广告关于此应用声明&#xff1a; 应用利用了安卓系统的辅助功能API&#xff0c;可以读取您手机屏幕上显示的所有内容&#xff0c;并且可以以您的名义进行屏幕点击等操作。* 轻量无广告&#xff0c;不联网&#xff0c;也不需要任何权限&#xff1b;* 请务必在系统设置中开启…

链表oj测试题(上)

链表的申明&#xff1a; struct ListNode {int val;struct ListNode* next; }; 1.题1 删除指定元素 例如&#xff1a;链表1 2 6 3 4 5 6&#xff0c;然后选择删除元素6&#xff0c;返回的链表为1 2 3 4 5 。 代码演示&#xff1a; typedef struct ListNode ListNode;List…

Linux文件 profile、bashrc、bash_profile区别

Linux系统中&#xff0c;有三种文件 出现的非常频繁&#xff0c;那就是 profile、bash_profile、bashrc 文件。 1、profile 作用 profile&#xff0c;路径&#xff1a;/etc/profile&#xff0c;用于设置系统级的环境变量和启动程序&#xff0c;在这个文件下配置会对所有用户…

学习刷题-12

3.22 hw机试【双指针】 Leetcode674 最长连续递增序列 给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 双指针 一个慢指针一个快指针 慢指针记录递增子序列起点&#xff0c;快指针去寻找还在当前递增子序列的最后一…

C++例子

#include<iostream> using namespace std;//抽象类 //抽象cpu类 class CPU { public:virtual void calcuate()0; }; //抽象显卡类 class VideoCard { public:virtual void display()0; }; //抽象内存条类 class Memory { public:virtual void storage()0;};//电脑类 clas…

leetcode 150.逆波兰表达式求值

题目 思路 逆波兰表达式也是经典的栈的应用问题。 先说什么是逆波兰表达式&#xff08;也叫后缀表达式&#xff09; 我们习惯的是这样的表达式&#xff1a;1 2 / 3 ,这也叫中缀表达式。 但是对于计算机来说不好理解&#xff0c;当从左扫描到 2 的时候还需要再判断2后面是什…

损失函数篇 | YOLOv8更换损失函数之CIoU / DIoU / EIoU / GIoU / SIoU / WIoU

前言:Hello大家好,我是小哥谈。损失函数是机器学习中用来衡量模型预测值与真实值之间差异的函数。在训练模型时,我们希望通过不断调整模型参数,使得损失函数的值最小化,从而使得模型的预测值更加接近真实值。不同的损失函数适用于不同的问题,例如均方误差损失函数适用于回…

vue2从基础到高级学习笔记

在实际的工作中,我常使用vue的用法去实现效果,但是你要是问我为什么这样写,它的原理是啥就答不上来了。对vue的认知一直停留在表面,写这篇文章主要是为了理清并弄透彻vue的原理。 学习目标 1 学会一些基本用法的原理 2 弄懂vue核心设计原理 3 掌握vue高级api的用法 一 vue…

基于springboot+vue的小型诊疗预约平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

蓝桥杯-单片机基础8——上下位机的串口通信设置(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

知识管理平台企业要怎么用?看完你就会了

在信息爆炸的现代社会&#xff0c;知识管理的重要性不言而喻。一个强大的知识管理平台&#xff0c;可以让团队分享和查找知识变得更容易&#xff0c;提升知识管理效率和整体工作效率。本文将引导你了解如何有效地利用知识管理平台。 1.确定目标和需求 在使用知识管理平台之前…

每日一题 --- 设计链表[力扣][Go]

设计链表 题目&#xff1a;707. 设计链表 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则…

使用ollama + webui 运行任意大模型

安装ollama https://hub.docker.com/r/ollama/ollama docker run -d -v ~/Documents/work/softs/docker/ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama验证安装 # 进入容器docker exec -it ollama bash # 运行大模型 ollama run llama2 # 发送请求&…

硬件学习件Cadence day15 做个笔记--PCB需要生成的文件格式

1.PCB生产文件类型 如下&#xff1a; 1、*.ASM 文件&#xff1a;为电子装配图文件。焊接厂可能需要。 2、*.CAM 文件&#xff1a;为PCB制版厂所需文件。 3、*.DXF 文件&#xff1a;为导出的PCB结构CAD文件。 4、*.PCB 文件&#xff1a;为PCB设计文件。 5、*.SMD 文件&#xff1…

什么是浏览器指纹识别?Maskfog指纹浏览器有用吗?

浏览器指纹识别是好是坏&#xff1f;这现在确实是一个有争议的话题。83%的消费者经常或偶尔会根据浏览历史记录看到广告。其实这就是利用了浏览器指纹技术。 如果您想了解浏览器指纹识别是什么&#xff0c;那就看下去&#xff01; 一、什么是浏览器指纹识别 浏览器指纹是指无…

JavaSE——数据类型与变量

1. 数据类型 在 Java 中数据类型主要分为两类&#xff1a; 基本数据类型 和 引用数据类型 。 基本数据类型有 四类八种 &#xff1a; 1. 四类&#xff1a;整型、浮点型、字符型以及布尔型 2. 八种&#xff1a; 数据类型关键字内存占用范围字节型byte1 个字节-128~127短整型…

计算机实体安全

计算机实体安全定义&#xff1a; 对场地环境、设施、设备和载体、人员采取的安全对策和措施。 一、计算机可靠性与故障分析 1.1 计算机的可靠性 可靠性 (狭义) ■计算机在规定时间与条件下完成规定功能的 概率 ■规定条件&#xff1a;环境条件&#xff0c;使用条件&#xff0…

iOS应用审核问题解决方案及优化方法 ✨

摘要 本文将针对iOS应用提交审核时可能遇到的问题&#xff0c;如“你必须在Xcode中添加com.apple.developer.game-center密钥”&#xff0c;以及突然间提交送审报错情况进行探讨。通过大量查询资料和尝试&#xff0c;结合案例分析&#xff0c;提供了解决方案和优化方法&#x…

常用相似度计算方法总总结

一、欧几里得相似度 1、欧几里得相似度 公式如下所示&#xff1a; 2、自定义代码实现 import numpy as np def EuclideanDistance(x, y):import numpy as npx np.array(x)y np.array(y)return np.sqrt(np.sum(np.square(x-y)))# 示例数据 # 用户1 的A B C D E商品数据 [3.3…

自己的博客阵地(互联网核心之一 DNS)

DNS(Domain Name System)是一种用于将易记的域名映射到计算机网络中的 IP 地址的系统。它充当互联网上计算机和网络设备的地址簿&#xff0c;使人们可以使用便于记忆的域名来访问网站&#xff0c;而不必记住复杂的数字IP地址。&#xff08;完全合格域名&#xff09; 名字号联系…
最新文章