滑动图片验证登录

3,253 阅读2分钟
可以直接显示图片拖动也可以点击之后再显示图片拖动

效果

屏幕录制2022-03-01-16.44.51.gif

template

<el-form-item v-if="!yanz">
  <div id="imgVer" style="display:inline-block;position:relative;"></div>
</el-form-item>

在mounted中执行方法其中 需要注意的是 采用了 jquery以及相关功能需要安装插件

const imgYan =()=> {
    var _self = context ;
    var config = {
        el:'$("#imgVer")',
        pl:_self,
        width:'360',
        height:'144',
        img:['在这配自己图片'],
        success:function () {
            setTimeout(function(){
                state.yanz = true ;
            },1100)
        },
        error:function () {
            state.yanz = false ;
        }
    }
    // 此方法在下面
    imgVer(config)
}
import $ from 'jquery';
export const imgVer = (Config) => {
// 缓存最后一次的pageX
let localPageX = ''
// fix兼容性
function getScroll() {
        var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        return {
            scrollLeft: scrollLeft,
            scrollTop: scrollTop
        }
}
function getPageX(e) {
        let pageX = ''
        if(inMobile){
            if(e.targetTouches[0]){
                pageX = e.targetTouches[0].pageX
                localPageX = pageX
            }else {
                // touchend的时候取缓存值
                pageX = localPageX
            }
        } else {
            pageX = e.pageX || e.clientX + getScroll().scrollLeft;
        }
        return pageX
}
const sUserAgent = navigator.userAgent.toLowerCase();
const inMobile = sUserAgent.includes('mobile')
var el = eval(Config.el);
var w = Config.width;
var h = Config.height;
var imgLibrary = Config.img;
var PL_Size = 48;
var padding = 20;
var MinN_X = padding + PL_Size;
var MaxN_X = w - padding - PL_Size - PL_Size / 6;
var MaxN_Y = padding;
var MinN_Y = h - padding - PL_Size - PL_Size / 6;
function RandomNum(Min, Max) {
var Range = Max - Min;
var Rand = Math.random();
if (Math.round(Rand * Range) == 0) {
    return Min + 1;
} else if (Math.round(Rand * Max) == Max) {
    return Max - 1;
} else {
    var num = Min + Math.round(Rand * Range) - 1;
    return num;
}
}
var imgRandom = RandomNum(1, imgLibrary.length);
var imgSrc = imgLibrary[imgRandom-1];
var X = RandomNum(MinN_X, MaxN_X);
var Y = RandomNum(MinN_Y, MaxN_Y);
var left_Num = -X + 10;

var html = '<div id="showTipTopMess" style="position:absolute; bottom:0px;border:1px solid #ddd;background:#f2ece1;opacity:0;display:none; transition:all .3s linear">';
html += '<div style="position:relative;overflow:hidden;width:' + w + 'px;">';
html += '<div style="position:relative;width:' + w + 'px;height:' + h + 'px;">';
html += '<img id="scream" src="' + imgSrc + '" style="width:' + w + 'px;height:' + h + 'px;">';
html += '<canvas id="puzzleBox" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:22222;"></canvas>';
html += '</div>';
html += '<div class="puzzle-lost-box" style="position:absolute;width:' + w + 'px;height:' + h + 'px;top:0;left:' + left_Num + 'px;z-index:111111;">';
html += '<canvas id="puzzleShadow" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:22222;"></canvas>';
html += '<canvas id="puzzleLost" width="' + w + '" height="' + h + '" style="position:absolute;left:0;top:0;z-index:333333;"></canvas>';
html += '</div>';
html += '<p class="ver-tips"></p>';
html += '</div>';
html += '<div class="re-btn"><a></a></div>';
html += '</div>';
// html += '<br>';

html += '<div id="showTipMess" style="position:relative;width:' + w + 'px;margin:auto; margin-top:10px;">';
html += '<div style="border:1px solid #c3c3c3;border-radius:24px;background:#ece4dd;box-shadow:0 1px 1px rgba(12,10,10,0.2) inset;">';
html += '<p id="hasReady"style="font-size:12px;color: #486c80;line-height:28px;margin:0;text-align:center;padding-right:22px;">按住左边滑块,拖动完成上方拼图</p>';
html += '</div>';
html += '<div class="slider-btn"></div>';
html += '</div>';
el.html(html);
function addImg(){
        var d = PL_Size / 3;
        var c = document.getElementById("puzzleBox");
        var ctx = c.getContext("2d");
        ctx.clearRect(0,0,c.width,c.height);
        ctx.globalCompositeOperation = "xor";
        ctx.shadowBlur = 10;
        ctx.shadowColor = "#fff";
        ctx.shadowOffsetX = 3;
        ctx.shadowOffsetY = 3;
        ctx.fillStyle = "rgba(0,0,0,0.7)";
        ctx.beginPath();
        ctx.lineWidth = "1";
        ctx.strokeStyle = "rgba(0,0,0,0)";
        ctx.moveTo(X, Y);
        ctx.lineTo(X + d, Y);
        ctx.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y);
        ctx.lineTo(X + 3 * d, Y);
        ctx.lineTo(X + 3 * d, Y + d);
        ctx.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d);
        ctx.lineTo(X + 3 * d, Y + 3 * d);
        ctx.lineTo(X, Y + 3 * d);
        ctx.closePath();
        ctx.stroke();
        ctx.fill();
        var c_l = document.getElementById("puzzleLost");
        var c_s = document.getElementById("puzzleShadow");
        var ctx_l = c_l.getContext("2d");
        var ctx_s = c_s.getContext("2d");
        ctx_l.clearRect(0,0,c_l.width,c_l.height);
        ctx_s.clearRect(0,0,c_s.width,c_s.height);
        var img = new Image();
        img.src = imgSrc;
        img.onload = function() {
            ctx_l.drawImage(img, 0, 0, w, h);
        }
        ctx_l.beginPath();
        ctx_l.strokeStyle = "rgba(0,0,0,0)";
        ctx_l.moveTo(X, Y);
        ctx_l.lineTo(X + d, Y);
        ctx_l.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y);
        ctx_l.lineTo(X + 3 * d, Y);
        ctx_l.lineTo(X + 3 * d, Y + d);
        ctx_l.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d);
        ctx_l.lineTo(X + 3 * d, Y + 3 * d);
        ctx_l.lineTo(X, Y + 3 * d);
        ctx_l.closePath();
        ctx_l.stroke();
        ctx_l.shadowBlur = 10;
        ctx_l.shadowColor = "black";
        ctx_l.clip();
        ctx_s.beginPath();
        ctx_s.lineWidth = "1";
        ctx_s.strokeStyle = "rgba(0,0,0,0)";
        ctx_s.moveTo(X, Y);
        ctx_s.lineTo(X + d, Y);
        ctx_s.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y);
        ctx_s.lineTo(X + 3 * d, Y);
        ctx_s.lineTo(X + 3 * d, Y + d);
        ctx_s.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d);
        ctx_s.lineTo(X + 3 * d, Y + 3 * d);
        ctx_s.lineTo(X, Y + 3 * d);
        ctx_s.closePath();
        ctx_s.stroke();
        ctx_s.shadowBlur = 20;
        ctx_s.shadowColor = "black";
        ctx_s.fill();
}
addImg();
var moveStart = '';
var timer ;
function showContainer(){
        timer = setTimeout(function(){
            $("#showTipTopMess").show().css({"bottom":"40px","opacity":"1"});
        },300)
    }
    // 直接显示 图片不是移入显示
    // showContainer()
function hideContainer(time){
        $("#showTipTopMess").css({"bottom":"0","opacity":"0"});
        clearTimeout(timer)
        setTimeout(function(){
            $("#showTipTopMess").hide()
        },time)
}
if(inMobile){
        const dom_imgVer = document.getElementById('imgVer')
        dom_imgVer.addEventListener('touchstart',function() {
            showContainer()
        })
        dom_imgVer.addEventListener('touchend',function() {
            hideContainer(3000)
        })
}else {
        $("#imgVer").hover(function(){
            /** 如果希望在鼠标移入的时候 显示图片 在这里执行方法 */
            showContainer()
        },function(){
            // 这里是关闭图片 移入再移出
            hideContainer(300)
        });
}

function isShow(){
        setTimeout(function() {
            $(".slider-btn").css({
                "left": '0',
                "transition": "left 0.5s"
            });
            $("#puzzleLost").css({
                "left": '0',
                "transition": "left 0.5s"
            });
            $("#puzzleShadow").css({
                "left": '0',
                "transition": "left 0.5s"
            });
        }, 1000);
   $(".slider-btn").removeClass("on")
}
function verifyStart(e, _this){
        e = e || window.event;
        $(_this).addClass("on");
        moveStart = getPageX(e);
}
function verifyEnd(e){
        e = e || window.event;
        // var moveEnd_X = e.pageX - moveStart;
        var moveEnd_X = getPageX(e) - moveStart;
        var ver_Num = X - 10;
        var deviation = 4;
        var Min_left = ver_Num - deviation;
        var Max_left = ver_Num + deviation;
        if (moveStart == '') {} else {
            if (Max_left > moveEnd_X && moveEnd_X > Min_left) {
                $(".ver-tips").html('<i style="background-position:-4px -1207px;"></i><span style="color:#42ca6b;">验证通过</span><span></span>');
                $(".ver-tips").addClass("slider-tips");
                $(".puzzle-lost-box").addClass("hidden");
                $("#puzzleBox").addClass("hidden");
                setTimeout(function() {
                    $(".ver-tips").removeClass("slider-tips");
                }, 2000);
                isShow();
                Config.success();
            } else {
                $(".ver-tips").html('<i style="background-position:-4px -1229px;"></i><span style="color:red;">验证失败:</span><span style="margin-left:4px;">拖动滑块将悬浮图像正确拼合</span>');
                $(".ver-tips").addClass("slider-tips");
                setTimeout(function() {
                    setTimeout(function(){
                        var p = RandomNum(1, imgLibrary.length);
                        imgSrc = imgLibrary[p-1];
                        $("#scream").attr({"src":imgSrc});
                        addImg();
                    },300)
                }, 500);
                setTimeout(function(){
                    $(".ver-tips").removeClass("slider-tips");
                },2000)
                isShow();
                Config.error();
            }
        }
        moveStart = '';
        $(".re-btn a").on("click", function() {
            Config.pl.imgVer(Config);
            $("#showTipTopMess").show().css({"bottom":"40px","opacity":"1"})
        })
}
if(inMobile){
        const dom_slider = document.getElementsByClassName('slider-btn')[0],
        dom_puzzleLost = document.getElementById('puzzleLost'),
        dom_puzzleShadow = document.getElementById('puzzleShadow');
        dom_slider.addEventListener('touchstart',function(e) {
            verifyStart(e, this)
        })
        ontouchmove = function(e) {
            e = e || window.event;
            // var moveX = e.pageX;
            var moveX = getPageX(e);
            var d = moveX - moveStart;
            if (moveStart == '') {} else {
                if (d < 0 || d > (w - padding - PL_Size)) {} else {
                    dom_slider.style.left = d + 'px'
                    dom_slider.style.transition ="inherit"
                    dom_puzzleLost.style.left = d + 'px'
                    dom_puzzleLost.style.transition ="inherit"
                    dom_puzzleShadow.style.left = d + 'px'
                    dom_puzzleShadow.style.transition ="inherit";
                }
            }
        };
        ontouchend = function(e) {
            verifyEnd(e)
        }
}else{
        // PC端
        $(".slider-btn").mousedown(function(e) {
            verifyStart(e, this)
        });
        onmousemove = function(e) {
            e = e || window.event;
            // var moveX = e.pageX;
            var moveX = getPageX(e)
            var d = moveX - moveStart;
            if (moveStart == '') {} else {
                if (d < 0 || d > (w - padding - PL_Size)) {
                } else {
                    $(".slider-btn").css({
                        "left": d + 'px',
                        "transition": "inherit"
                    });
                    $("#puzzleLost").css({
                        "left": d + 'px',
                        "transition": "inherit"
                    });
                    $("#puzzleShadow").css({
                        "left": d + 'px',
                        "transition": "inherit"
                    });
                }
            }
        };
        onmouseup = function(e) {
            verifyEnd(e)
        }
  }
}