按照自己的思路写了一个拖动验证,不知道别人是不是这样写的,我觉得方法应该差不多。不废话,上代码。

<?php
 require_once 'Check.php';

 if($data = Check::create()){


     $x = $data['x'];
     $y = ($data['y'] - 5).'px';
     $name = $data['name'];


     session_start();//开启会话,保存验证信息
     $_SESSION['x'] = $x;
     $_SESSION['name'] = $name;
     $_SESSION['check'] = false; //刷新本页面要重新验证。

 }
 
?>


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>demo7</title>
    <style>
        #body{
            position: relative;
            width: 470px;
            height: 50px;
            margin: 400px auto;
        }
        #checkingBody{
            position: absolute;
            width: 470px;
            box-sizing: border-box;
            padding: 10px 10px;
            height: 160px;
            background: #E8E8E8;
            left: 0;
            top:-170px;
            display: none;
        }
        #checkingPack{
            width: 100%;
            height: 100%;
            position: relative;
        }

        #checking{
            width: 50px;
            height: 50px;
            position: absolute;
            left:0;
            top:<?php echo $y ?>;
            border: 5px solid #00FFFF;
        }

        #sliderPack{
            width: 440px;
            height: 50px;
            border: 1px solid darkgrey;
            position: relative;
            margin-left: 15px;
        }
        #slider{
            width: 50px;
            background: darkgrey;
            height: 50px;
            position: absolute;
        }

        #checkingPackImage{
            width:100%;
            height:100%;
        }
        #checkingImage{
            width: 100%;
            height: 100%;
        }


    </style>
</head>
<body>
    <div id="body">
        <div id="checkingBody">
            <div id="checkingPack">
                <img  id="checkingPackImage"  src="<?php echo 'check/'.$name.'A.jpg' ?>" alt="<?php echo $name.'A.jpg' ?>">
                <div id="checking">
                    <img id="checkingImage" src="<?php echo 'check/'.$name.'B.jpg' ?>" alt="<?php echo $name.'B.jpg'  ?>">
                </div>
            </div>
        </div>
        <div id="sliderPack">
            <div id="slider"></div>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
    <script>
        $(function () {
            let sliderPack = document.getElementById("sliderPack");
            let slider = document.getElementById("slider");
            let checking = document.getElementById("checking");
            let checkingBody = document.getElementById("checkingBody");
            let isSending = false;
            let differenceX;
            let isDown = false;
            let isMove = false;

            slider.onmousedown  = function (e) {
                differenceX = e.clientX - this.offsetLeft;
                this.style.cursor = "move";
                checkingBody.style.display = "block";
                isDown = true;
            };

            sliderPack.onmousemove = function (e) {
                if(!isDown || isSending){
                    return false;
                }

                isMove = true;

                let newLeft = e.clientX - differenceX;

                if(newLeft<0){
                    newLeft = 0;
                }

                if(newLeft>390){
                    newLeft = 390;
                }

                slider.style.left = newLeft + "px";
                checking.style.left = newLeft + "px";

                setInterval(function(){  //移动的时候,执行监听函数。
                    let x1 = slider.style.left; //记录x1
                    setTimeout(function () {
                        let x2 = slider.style.left; // 300毫秒后记录x2
                        if(x1===x2 && !isSending && isMove){ //如果x1 等于 x2 说明鼠标停留了
                            isSending = true; //提交标识开启,防止多次提交。
                            isMove = false; //移动标识改成false,这样做是为了让用户验证失败后要再次移动才发送验证。
                            $.ajax({
                                url:"demo8.php",
                                data:{
                                    x:parseInt(slider.style.left)//把距离左边的距离去掉px 再发送
                                },
                                type:"get",
                                dataType:"json",
                                success:function (e) {
                                    if(e.message==="SUCCESS"){
                                        //验证成功
                                    }else{
                                        //验证失败
                                        isSending = false;
                                    }
                                },
                                error:function () {
                                    isSending = false;
                                }
                            })
                        }
                    },300)
                },500);

            };
            sliderPack.onmouseup = function () {
                if(!isDown){
                    return false
                }
                isDown = false;
                slider.style.cursor = "default";
            };
            sliderPack.onmouseleave = function () {
                isDown = false;
                slider.style.cursor = "default";
                checkingBody.style.display = "none";
            }
        })
    </script>
</body>
</html>

这里用了混编的方式,只是为了演示 。

<?php


class Check
{
    static function create(){

        //生成一个随机坐标,作为裁剪图片左上角的坐标。
        $x = mt_rand(100,395); //最左的坐标设置成100,为了让裁剪位置尽量出现在右边的位置,好让用户滑动一定的距离。
        $y = mt_rand(5,85);


       

        $image = imagecreatefromjpeg('check.jpg'); //准备一张宽450 高140 的图片作为底片。

        $newImage = imagecreatetruecolor(50,50); //创建一个空白的图片。

        imagecopyresampled($newImage,$image,0,0,$x,$y,50,50,50,50); //把底片的一部分裁剪到空白的图片。


        $gray = imagecolorallocate($image,156,156,156); //创建灰色的画笔。
        imagefilledrectangle($image, $x, $y,$x+50,$y+50,$gray); //填充一个灰色的矩形并覆盖到裁剪的位置。



        imagesetthickness($image,6); //设置画线的宽度,准备画一个粗边框的矩形在裁剪的位置,突出裁剪的位置。

        $cyan = imagecolorallocate($image,0,255,255); //创建青色的画笔。
        imagerectangle($image,$x-3,$y-3,$x+53,$y+53,$cyan); //画青色的矩形。

        ini_set('date.timezone','Asia/Shanghai'); //设置时区。
        $dateTime = new DateTime(); //创建一个DateTime对象,用来获取毫秒。
        $name = date('Y').date('m').date('d').date('H').date('i').$dateTime->format('u').mt_rand(0,9);
        //以时间加随机数的形式作为图片名字。

        $path = 'check/'; //图片保存目录

        imagejpeg($image,$path.$name.'A.jpg'); //保存图片,底片以大写字母A结尾。
        imagejpeg($newImage,$path.$name.'B.jpg'); //保存图片,裁剪的图片以大写字母B结尾。

        imagedestroy($newImage); //释放内存。
        imagedestroy($image); //释放内存。

        $data['x'] = $x;
        $data['y'] = $y;
        $data['name'] = $name;

        //把坐标和名字赋值给数组。

        return $data;//返回数组。


    }
}

这个静态方法作用是创建验证用的图片。 

<?php

$newX = $_GET['x'];

if(empty($newX)){
    die(json_encode('')); //如果没接收到x,返回错误信息并结束脚本
}
/*
 *
 *
 * 这里可以写限制访问次数的脚本,防止别人攻击这个接口。
 *
 *
 *
 *
 *
 *
 *
 *
 */

session_start(); //开启会话

$x = $_SESSION['x'];

if(empty($x)){
    die(json_encode('')); //如果会话没有保存到x的信息,返回错误信息并结束脚本
}


if($newX > $x - 10 &&  $newX < $x +10){
    $_SESSION['check'] = true; //如果用户发送的 x 在 会话里 保存的x 的一定范围内 则验证通过
    $data['message'] = 'SUCCESS';
    echo json_encode($data);//返回拖动验证成功标识

}else{

    echo json_encode(''); //返回验证失败信息
    /**
     *
     *
     * 这里面可以写错误次数过多的脚本。
     *
     *
     *
     *
     *
     *
     */
}

验证坐标是否正确

<?php




session_start();

if($_SESSION['check']){
    //拖动验证成功,执行验证用户信息

    /*
    *
    *
    * 验证用户信息。
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    */

    //
    $_SESSION['check']  = false; //如果验证用户信息成功,则改成false,拖动验证成功一次只能登录一个用户
}

验证用户信息是否正确。

以上就是全部代码。