zoukankan      html  css  js  c++  java
  • 实现拼图滑动验证码

    实现拼图滑动验证码

    拼图滑动验证码的纯前端简单实现,重要部分都已标注注释,如果需要配合后端可以参考此思路,后端处理图片生成一个带缺口的背景图与一个符合缺口的拼图,并将取得拼图块的位置记录到SESSION,将图片与拼图传给前端展示,当用户拖动并松开鼠标后将鼠标轨迹与停留位置发送到后端,后端从SESSION中取得位置信息并与前端传递的位置进行对比,有需要的话可以分析此用户轨迹用以区分人机,如果位置偏差小于一定阈值则认为拼图成功。

    实例

    <!DOCTYPE html>
    <html>
    <head>
        <title>滑动拼图验证码</title>
        <link rel="stylesheet" type="text/css" href="https://at.alicdn.com/t/font_1582902_u0zm91pv15i.css">
        <style type="text/css">
            .verify-slide-con{ /* 滑动拼图容器块 */
                 360px;
                padding: 10px 20px;
                border: 1px solid #eee;
            }
            .img-con{ /* 图片容器块 */
                 100%;
                height: 200px;
                display: flex;
                justify-content: center;
                align-items: center;
                overflow: hidden;
                border: 1px solid #eee;
                position: relative;
            }
            .img-con > .slide-block{ /* 图片区域的滑块 */
                top: 0;
                left: 0;
                position: absolute;
                height: 40px;
                 40px;
                display: none;
                background-repeat: no-repeat;
                background-attachment: scroll;
                background-size: 360px 200px;
                z-index: 10;
                box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.4), 0 0 10px 0 rgba(90, 90, 90, 0.4);
            }
            .img-con > .slide-block-mask{ /* 图片区域的空缺区域 */
                top: 0;
                left: 0;
                position: absolute;
                height: 40px;
                 40px;
                display: none;
                background-color: rgba(0, 0, 0, 0.4);
            }
            .img-con > .img{ /* 图片 */
                 100%;
                height: 100%;
            }
            .img-con > .loading{ /* 加载中样式 */
                 unset;
                height: unset;
            }
            .slide-con{ /* 滑块容器 */
                height: 40px;
                margin: 10px 0;
                position: relative;
                border: 1px solid #eee;
            }
            .slide-con > .slide-btn{ /* 滑动按钮 */
                height: 40px;
                 40px;
                position: absolute;
                background: #4C98F7;
                display: flex;
                justify-content: center;
                align-items: center;
                cursor: pointer;
            }
            .icon-arrow-right{ /* 右箭头 */
                font-size: 30px;
                color: #fff;
            }
            .operate-con{ /* 操作容器块 */
                border-top: 1px solid #eee;
                height: 30px;
                padding: 5px 0 0 5px;
                display: flex;
                align-items: center;
            }
            .icon-shuaxin1{ /* 刷新按钮 */
                color: #777;
                font-size: 20px;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
        <div class="verify-slide-con"> <!-- 滑动拼图容器块 -->
            <div class="img-con"> <!-- 图片容器块 -->
                <img class="img"> <!-- 图片 -->
                <div class="slide-block"></div> <!-- 拼图 -->
                <div class="slide-block-mask"></div> <!-- 缺口 -->
            </div>
            <div class="slide-con"> <!-- 滑块容器 -->
                <div class="slide-btn"> <!-- 滑动按钮 -->
                    <i class="iconfont icon-arrow-right"></i> <!-- 图标 -->
                </div>
            </div>
            <div class="operate-con"> <!-- 操作容器块 -->
                <i id="refresh" class="iconfont icon-shuaxin1"></i> <!-- 刷新按钮 -->
            </div>
        </div>
    </body>
    <script type="text/javascript">
        (function(){
            var imgList = [ // 图片组
                "http://www.sdust.edu.cn/__local/9/7A/B1/F29B84DEF72DD329997E8172ABA_664BA3EF_32466.jpg",
                "http://www.sdust.edu.cn/__local/B/F3/E4/693AB931C9FFB84646970D53BFE_C506394A_4282CA.jpg",
                "http://www.sdust.edu.cn/__local/F/7A/AA/E1459849AA8AB0C89854A41BD41_BF3BD857_BC0D8.jpg",
                "http://www.sdust.edu.cn/__local/1/95/CB/EDC1450B8FD1B8A25FAAC726AA4_A36D4253_16C91.jpg",
            ];
            var imgCon = document.querySelector(".img-con"); // 图片容器元素引用
            var img = document.querySelector(".img-con > .img"); // 图片元素引用
            var slideBlock = document.querySelector(".img-con > .slide-block"); // 滑块元素引用
            var slideBlockMask = document.querySelector(".img-con > .slide-block-mask"); // 缺口元素引用
            var slideCon = document.querySelector(".slide-con"); // 滑动容器引用
            var slideBtn = document.querySelector(".slide-con > .slide-btn"); // 滑块按钮引用
            var refreshBtn = document.querySelector("#refresh"); // 刷新按钮引用
            function randomInt(min=0, max=1) { // 生成随机数
                return min + ~~((max-min)*Math.random()) // min <= random < max 
            }
            function initSlider(){
                var maxTop = imgCon.offsetHeight - 
                    ~~(window.getComputedStyle(slideBlock).getPropertyValue("height").replace("px","")); // 获取最大Y轴偏移距离
                var maxRight = imgCon.offsetWidth - 
                    ~~(window.getComputedStyle(slideBlock).getPropertyValue("width").replace("px","")); // 获取最大X轴偏移距离
                var randPosY = randomInt(0, maxTop); // 随机Y轴偏移
                var randPosX = randomInt(60, maxRight); // 随机X轴偏移
                slideBtn.onmousedown = function(e){
                    slideBlock.style.display = "block"; // 显示拼图
                    slideBlock.style.top=`${randPosY}px`; // 拼图Y轴偏移
                    slideBlock.style["background-position"] = `-${randPosX}px -${randPosY}px`; // 指定背景图位置
                    slideBlockMask.setAttribute("style", `display:block;top:${randPosY}px;left:${randPosX}px`); // 显示缺口并指定位置
                    var edgeX = e.clientX; // 鼠标点击位置
                    document.onmousemove = event => {
                        var relativeX = event.clientX - edgeX; // 鼠标移动距离
                        if(relativeX<0 || relativeX>imgCon.offsetWidth-this.offsetWidth) return void 0; // 判断是否超出滑动容器块 超出则不移动
                        slideBlock.style.left = relativeX + "px"; // 移动拼图
                        this.style.left =  relativeX + "px"; // 移动滑块按钮
                    }
                    document.onmouseup = function() {
                        this.onmousemove = null; // 撤销事件
                        this.onmouseup = null; // 撤销事件
                        if(Math.abs(slideBlock.offsetLeft - slideBlockMask.offsetLeft)<=2) alert("验证成功"); // 偏移距离小于2则认为成功
                        else alert("验证失败"); // 否则失败
                        slideBlock.style.left = 0; // 拼图归位
                        slideBtn.style.left =  0; // 滑块按钮归位
                    };
                }
            }
            function switchImg(){
                slideBlock.style.display = "none"; // 不显示拼图
                slideBlockMask.style.display = "none"; // 不显示缺口
                img.classList.add("loading"); // 指定图片加载中样式
                img.src="https://cdn.jsdelivr.net/gh/sentsin/layui@15d7241/dist/css/modules/layer/default/loading-2.gif"; // 加载动画
                var newSrc = imgList[randomInt(0, 4)]; // 随机加载图片
                var tmp = new Image(); // 隐式加载图片
                tmp.src = newSrc; // 指定src
                tmp.onload = function(){
                    img.classList.remove("loading"); // 撤销loading
                    img.src = newSrc; // 指定src 此时从缓存加载图片
                    slideBlock.style["background-image"] = `url(${newSrc})`; // 拼图背景
                    initSlider(); // 初始化滑块
                }
            }
            (function(){
                switchImg(); // 加载图片
                refreshBtn.addEventListener("click", e => switchImg()); //  刷新按钮绑定事件
            })();
        })();
    </script>
    </html>
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://zhuanlan.zhihu.com/p/42082496
    https://github.com/himushroom/verify-slide
    https://www.cnblogs.com/xiaoshen666/p/10968750.html
    
  • 相关阅读:
    微信第三方平台开发之代小程序实现业务
    解决Chrome网页编码显示乱码的问题
    .Net Core 使用 System.Drawing.Common 在CentOS下报错
    CentOS安装nmap端口查看工具
    解决Nginx反向代理不会自动对特殊字符进行编码的问题 如gitblit中的~波浪线
    Centos7最小安装化后安装图形界面
    手把手教您在 Windows Server 2019 上使用 Docker
    windows10下安装docker报错:error during connect
    git删除远程分支
    linux下shell显示git当前分支
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/13585107.html
Copyright © 2011-2022 走看看