纯js滑块验证,并适配手机,PC

这是一个使用HTML、CSS和JavaScript编写的简易滑动拼图解锁示例。代码创建了一个包含图片背景的canvas元素,通过JavaScript生成随机位置的拼图缺口,并监听鼠标和触摸事件来处理滑动验证。当用户成功将滑块拖动到正确位置时,显示验证成功信息,否则重置并提示验证失败。
摘要由CSDN通过智能技术生成
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>简易滑动拼图解锁</title>
  <style>
    * {
      margin: 0px;
      padding: 0px;
    }

    .topCanvas img,
    .topCanvas canvas {
      width: 330px;
      height: 155px;
    }

    img {
      display: none;
    }

    #myCanvas {
      position: absolute;
      float: left;
    }
    .topCanvas{
      position: relative;
    }
    .topCanvas .prompt{
      width: 330px;
      height: 40px;
      position: absolute;
      bottom: 4px;
      left: 0px;
      color: #fff;
      font-size: 15px;
      line-height: 40px;
      display: none;
    }

    .verify {
      position: relative;
      width: 330px;
      height: 40px;
      line-height: 40px;
      text-align: center;
      border: 1px solid #ddd;
      color: #333;
    }

    .verify .leftbar {
      position: absolute;
      left: -1px;
      top: -1px;
      width: 40px;
      height: 39px;
      background: #f0fff0;
      border: 1px solid #ddd;
    }
    .verify .leftbar .slide {
      position: absolute;
      width: 40px;
      height: 40px;
      border-right: 1px solid #ddd;
      border-left: 1px solid #fff;
      background: url("./img/bg/icon.png") no-repeat center;
      background-size: 20px 20px;
      background-color: #fff;
    }
    /* position:relative 移动端左移会滑动 */
    /* position:fixed 解决左移滑动问题*/

    .lockBox {
      position: fixed;
    }

    .bigBox {
      width: 330px;
      margin: 10px auto;
    }
  </style>
</head>

<body>
  <div class="bigBox">
    <!-- 图片 -->
    <div class="lockBox">
      <div class="topCanvas">
        <img src="./img/bg/star-squashed.jpg" alt="随机拼图">
        <canvas id="myCanvas"></canvas>
        <canvas id="block"></canvas>
        <div class="prompt">验证失败</div>
      </div>
      <!-- 滑块 -->
      <div class="verify">
        <!-- 滑块 -->
        <div class="leftbar">
          <div class="slide">
          </div>
        </div>
      </div>
    </div>
  </div>
<script>
  const w = 330 // canvas宽度
  const h = 155 // canvas高度
  const l = 35 // 滑块边长
  const r = 5 // 滑块半径
  const PI = Math.PI
  const L = l + r * 2 + 3 // 滑块实际边长

  // 拼图滑块
  var c = document.querySelector("#myCanvas");
  var ctx = c.getContext("2d");

  // 拼图背景图
  var c2 = document.querySelector("#block");
  var ctx2 = c2.getContext("2d");
  var img = document.querySelector("img");

  // 绘制拼图背景
  function drawImage() {
    ctx.drawImage(img, 0, 0, 330, 155);
    ctx2.drawImage(img, 0, 0, 330, 155);
  }

  img.onload = function() {
    // 初始化拼图
    drawImage();
  }

  // 拼图滑块挖掘
  function drawPath(ctx, x, y, operation) {
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
    ctx.lineTo(x + l, y)
    ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
    ctx.lineTo(x + l, y + l)
    ctx.lineTo(x, y + l)
    ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
    ctx.lineTo(x, y)
    ctx.lineWidth = 1
    ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
    ctx.stroke()
    ctx.globalCompositeOperation = 'destination-over'; //重要
    operation === 'fill' ? ctx.fill() : ctx.clip()
  }

  // 随机位置但是要同高度
  function randomNum(start, end) {
    return Math.floor(Math.random() * (end - start) + start);
  }

  // 随机位置创建拼图
  let x = randomNum(L + 10, w - L - 20);
  let y = randomNum(10 + 2 * r, h - L - 20);

  // 不动的挖空
  drawPath(ctx2, x, y, 'fill');
  // 滑块切割,
  drawPath(ctx, x, y, 'clip');
  // 控制同等高度,定位在左边
  document.querySelector("#myCanvas").style.left = -x + 'px';
  // 网页端滑动解锁 事件
  // 监听滑块事件
  document.querySelector(".slide").onmousedown = function(e) {
    //获取相对的时间
    let startMoveTime = new Date();
    document.onmousemove = function(e2) {
      // 最大滑动距离为下方盒子长-滑块长
      //范围内拖动
      if (e2.clientX > e.clientX && e2.clientX - e.clientX <= w - L + 10) {
        // 使得滑块和拼图一起动
        document.querySelector(".slide").style.left = e2.clientX - e.clientX + 'px';
        document.querySelector("#myCanvas").style.left = -x + e2.clientX - e.clientX + 'px';
        document.querySelector(".slide").style.backgroundColor = 'rgb(51,122,183)';
        document.querySelector(".leftbar").style.width = e2.clientX - e.clientX + 'px';
        document.querySelector(".leftbar").style.borderColor = "rgb(51,122,183)";
      }
      document.onmouseup = function() {
        // 判断拼图位置是否正确,拖拉距离是否是随机生成的拼图x
        let result = false;
        // 正确提示正确,误差为10以内为正确
        if (e2.clientX - e.clientX - 10 <= x && x <= e2.clientX - e.clientX + 10) {
          result = true;
          // 验证成功
          let endMovetime = new Date();
          let timer = ((endMovetime - startMoveTime)/1000).toFixed(2)
          document.querySelector(".slide").style.backgroundColor = 'rgb(92,184,92)';
          document.querySelector(".slide").style.backgroundImage = 'url("./img/bg/success.png")';
          document.querySelector(".leftbar").style.width = e2.clientX - e.clientX + 'px';
          document.querySelector(".leftbar").style.borderColor = "rgb(92,184,92)";
          document.querySelector(".prompt").innerHTML = timer+"s验证成功";
          document.querySelector(".prompt").style.display = "block";
          document.querySelector(".prompt").style.backgroundColor = 'rgb(92,184,92,.5)';
          clearInterval(timer);
        } else {
          // 验证失败
          document.querySelector(".slide").style.backgroundColor = 'rgb(217,83,79)';
          document.querySelector(".slide").style.backgroundImage = 'url("./img/bg/error.png")';
          document.querySelector(".leftbar").style.width = e2.clientX - e.clientX + 'px';
          document.querySelector(".leftbar").style.borderColor = "rgb(217,83,79)";
          document.querySelector(".prompt").innerHTML = "验证失败";
          document.querySelector(".prompt").style.display = "block";
          document.querySelector(".prompt").style.backgroundColor = 'rgba(217,83,79,.5)';
          location.reload();
        }
        // 解除以下事件
        document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  }
  // 移动端
  document.querySelector(".slide").ontouchstart = function(e) {
    let touch = e.targetTouches[0];
    let startMoveTime = new Date();
    document.ontouchmove = function(e2) {
      let touch2 = e2.targetTouches[0];
      // 最大滑动距离为下方盒子长-滑块长
      //范围内拖动
      if (touch2.pageX > touch.pageX && touch2.pageX - touch.pageX <= w - L + 10) {
        // 使得滑块和拼图一起动
        document.querySelector(".slide").style.left = touch2.pageX - touch.pageX + 'px';
        document.querySelector("#myCanvas").style.left = -x + touch2.pageX - touch.pageX + 'px';
        document.querySelector(".slide").style.backgroundColor = 'rgb(51,122,183)';
        document.querySelector(".leftbar").style.width = touch2.pageX - touch.pageX + 'px';
        document.querySelector(".leftbar").style.borderColor = "rgb(51,122,183)";


      }
      document.ontouchend = function() {
        // 判断拼图位置是否正确,拖拉距离是否是随机生成的拼图x
        let result = false;
        let endMovetime = new Date();
        let timer = ((endMovetime - startMoveTime)/1000).toFixed(2)
        // 正确提示正确,误差为10以内为正确
        if (touch2.pageX - touch.pageX - 10 <= x && x <= touch2.pageX - touch.pageX + 10) {
          result = true;
          // 滑块消失
          document.querySelector(".slide").style.backgroundColor = 'rgb(92,184,92)';
          document.querySelector(".slide").style.backgroundImage = 'url("./img/bg/success.png")';
          document.querySelector(".leftbar").style.width = touch2.pageX - touch.pageX + 'px';
          document.querySelector(".leftbar").style.borderColor = "rgb(92,184,92)";
          document.querySelector(".prompt").innerHTML = timer+"s验证成功";
          document.querySelector(".prompt").style.display = "block";
          document.querySelector(".prompt").style.backgroundColor = 'rgb(92,184,92,.5)';
        } else {
          // 验证失败
          document.querySelector(".slide").style.backgroundColor = 'rgb(217,83,79)';
          document.querySelector(".slide").style.backgroundImage = 'url("./img/bg/error.png")';
          document.querySelector(".leftbar").style.width = touch2.pageX - touch.pageX + 'px';
          document.querySelector(".leftbar").style.borderColor = "rgb(217,83,79)";
          document.querySelector(".prompt").innerHTML = "验证失败";
          document.querySelector(".prompt").style.display = "block";
          document.querySelector(".prompt").style.backgroundColor = 'rgba(217,83,79,.5)';
          location.reload();
        }

        // 解除以下事件
        document.ontouchmove = null;
        document.ontouchend = null;
      }
    }
  }

</script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值