首页 > 其他分享 >手撸一个简单的滑块验证码

手撸一个简单的滑块验证码

时间:2023-04-13 19:33:37浏览次数:27  
标签:canvas const 滑块 img image 验证码 简单 dw dragElement

使用过很多次滑块验证码的功能,偶然一次想起来,能不能简单的实现一个呢,于是就尝试了一下,然后记录下来了,图个乐子。

思路

  • 首先是绘制一张图片,自然而然,要用canvas了,就像下面这样,首先加载一张图片,然后去绘制到canvas中。
<div id="validate">
   <canvas id="canvas"></canvas>
</div>
<script>
   const canvas = document.getElementById('canvas');
   const ctx = canvas.getContext('2d');
   // 加载图片
   const loadImage = (url) => {
      return new Promise((resolve, reject) => {
        const image = new Image();
        image.src = url;
        image.crossOrigin = 'anonymous';
        image.onload = () => {
          resolve(image);
        };
        image.onerror = () => {
          reject();
        }
      });
  };
  const renderImage = (image) => {
      const w = image.width;
      const h = image.height;
      canvas.width = w;
      canvas.height = h;
      ctx.drawImage(image, 0, 0, w, h);
      return [w, h];
  };
  // 函数入口
  const start = () => {
      loadImage(url).then(renderImage).catch(() => {
        console.log('图片加载失败');
      });
  };

  start();
</script>
  • 接下来呢,肯定就是扣出一块区域了,把原图的区域清空,然后把该区域转化成一张新的可拖拽的图片。
const clipImage = () => {
    // 设置滑块的宽高
    const dw = 50;
    const dh = 50;
    // 随机生成空缺的x坐标
    const x = Math.floor(Math.random() * (w - 2 * dw) + dw);
    // y坐标就固定在中间
    const y = (h - dh) / 2;
    // 获取到这块区域的ImageData对象
    const imageData = ctx.getImageData(x, y, dw, dh);
    // 清空这块区域
    ctx.clearRect(x, y, dw, dh);
    // 使用一个临时的canvas承载这个ImageData去生成滑块图片
    let avatarCanvas = document.createElement("canvas");
    avatarCanvas.width = dw;
    avatarCanvas.height = dh;
    let avatarCtx = avatarCanvas.getContext("2d");
    avatarCtx.putImageData(imageData, 0, 0);
    let avatarDataUrl = avatarCanvas.toDataURL();
    const img = document.createElement('img');
    img.src = avatarDataUrl;
    img.style.top = `${y}px`;
    img.style.left = 0;
    // 图片可以拖拽
    img.draggable = true;
    // 挂载到页面上,样式使用绝对定位固定到最左侧的中间位置
    validate.appendChild(img);
    return [img, x];
}
  • 最后呢,就处理一下图片的滑动事件,每次拖动的时候去修改img的left值,然后结束的时候就判断一下距离之前的随机x是否在一个可接受范围内就ok了。这个地方有一个注意点,就是图片拖拽的时候,默认会出现一个阴影,和原图片一样,会感觉很丑,可以设置一个空标签来隐藏这个阴影。
const handlerDrag = (img, x) => {
    let startX = 0;
    img.ondragstart = (e) => {
        startX = e.pageX;
        // // create an empty element
        dragElement = document.createElement("span");
        dragElement.innerHTML = "&nbsp;";
        dragElement.style.position = "absolute";
        dragElement.style.left = "-1000%";

        // add the element to the dom
        document.body.appendChild(dragElement);

        //set it as the drag image
        event.dataTransfer.setDragImage(dragElement, 0, 0);
    }
    img.ondrag = (e) => {
        if (e.pageX === 0) {
          return;
        }
        const deltaX = e.pageX - startX;
        img.style.left = `${deltaX}px`;
    };
    img.ondragend = (e) => {
        const deltaX = e.pageX - startX;
        if(Math.abs(deltaX - x) < 50) {
          alert('验证成功');
        } else {
          alert('验证失败');
        }
        img.draggable = false;
    }
}
  • 最后把之前的代码整合一下,其实就是在初始方法中去以此调用就好了。
const start = () => {
  loadImage(url).then(image => {
      // 这个地方是不是很眼熟,上一个函数的执行结果,是下一个函数的参数,这个大家有兴趣的可以试试,实现一个compose函数了,类似compose: (fns: Array<(arg1, arg2...) => Array<any>) => any;
      const [w, h] = renderImage(image);
      const [img, x] = clipImage(w, h);
      handlerDrag(img, x);
  }).catch(() => {
    console.log('图片加载失败');
  });
};

效果图

start.png

end.jpg

小结

最后呢,我想说的是,这个肯定还有很多优化的地方,仅仅是提供一种实现思路,代码上也有更精简的写法,欢迎大家交流学习。

标签:canvas,const,滑块,img,image,验证码,简单,dw,dragElement
From: https://www.cnblogs.com/aloneMing/p/17316108.html

相关文章

  • javaweb验证码
    publicclassmyfunction{publicstaticStringgetRandString(intlength){Stringstr="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";Randomrandom=newRandom();StringBuffersb=newStringBuffe......
  • 【验证码逆向专栏】某验深知 V2 业务风控逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作......
  • 【验证码逆向专栏】某验深知 V2 业务风控逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作......
  • 登录功能实现之图片验证码二进制编码解决方法
    在使用vue开发页面的登录功能时候经常会遇到后端返回的二进制的图片编码。返回的大概形式类似于这样前端需要使用base64来进行转码显示 上代码  以上是一个比较简单的接口请求,使用的是以下的函数进行转化的  转化完成之后保存起来然后进行回显就行了......
  • 价值投资中简单实用的基本原则是什么?
    在投资股票时,深入的研究有利于得出正确的判断,系统的方法有利于做出明智的决策,支付合理的价格才能获得丰厚的利润,这是投资中的基本道理。价值投资法一点也不神秘,巴菲特曾经感慨道:“正是因为‘价值投资’太简单,所以人们不太愿意传授它。”投资者不需要复杂的经济模型,只要你拥有正确......
  • 让万物互联更简单 化繁为简 助推物联华普物联
    华普物联科技是一家专注于物联网领域,为客户提供企业级物联网通信产品以及物联网IoT领域“云+管+端”的行业物联网数据传输解决方案的高新技术企业。产品包括物联网网关、工业无线路由器、LoRa基站、DTU、RTU、远程IO等产品,以及支持边缘计算及云端部署的物联网平台。专注于物联网领......
  • ObjectARX 构建鼠标跟随图像之acedAddSupplementalCursorImage简单实例
    源ObjectARX2015新增了一个apiacedAddSupplementalCursorImage代码 CBitmapcbmp; cbmp.m_hObject=(HBITMAP)::LoadImage(NULL,_T("d:\\test.bmp"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE); BITMAPbm; cbmp.GetBitmap(&bm); intnByte=bm.bmBitsPixel/......
  • go验证码的使用
    前言:go验证码演示地址:https://captcha.mojotv.cn/正文:验证码包下载goversion>1.11goget-ugithub.com/mojocn/base64Captcha 验证码展示到页面示例:使用gonethttp包显示验证码 import("encoding/json""github.com/mojocn/base64Captcha""htm......
  • Go sync.Once:简约而不简单的并发利器
    原创文章,如需转载请联系作者:陈明勇公众号:Go技术干货简介在某些场景下,我们需要初始化一些资源,例如单例对象、配置等。实现资源的初始化有多种方法,如定义package级别的变量、在init函数中进行初始化,或者在main函数中进行初始化。这三种方式都能确保并发安全,并在程序启动......
  • ImGui 简单使用
    主窗口......