婚恋app源码也能实现滑动验证码,具体该如何做呢?

前言

滑动验证码相信大家肯定会经常遇到,其实在婚恋app源码开发时,我们也可以实现该功能,这样就能更好的保护用户信息和平台数据的安全,具体应该如何做呢?

技术实现

接下来将会以我的思路来带大家在婚恋app源码中实现滑动验证码组件。

1. 明确功能

在开发前我们首先要明确要实现哪些功能:

1、随机图片(这里不做过多描述,采用Picsum实现)
2、位置随机的镂空图案绘制
3、利用canvas进行图案裁剪
4、可滑动控制的拖拽滑块
5、图片加载时的loading效果
6、在婚恋app源码中能实现刷新按钮的点击
7、验证拖拽位置是否满足要求
在这里插入图片描述

2. 基本框架

我们先搭建出基本的框架

<div v-if="visiblity" class="slidingWrap">
    <div class="slidingTitle"></div>
    <!-- 画布区域 -->
    <div class="canvasArea">
      <!-- 主要渲染整体背景及镂空图案 -->
      <canvas class="canvas-bg" :width="width" :height="height"></canvas>
      <canvas
        class="block"
        :height="height"
        :style="{ left: `${blockLeft}px` }"
      ></canvas>
    </div>
    <!-- 底部滑块 -->
    <div
      :class="['sliderWrap', status]"
      :style="{ width: `${width}px` }"
      @mouseleave="handleDrapUp"
    >
      <div
        class="progress"
        :style="{
          width: `${blockLeft}px`
        }"
      ></div>
      <div
        class="slider-block"
        ref="slider"
        :style="{ left: `${blockLeft}px` }"
        @mousedown="handleDrapDown"
        @mouseup="handleDrapUp"
        @mousemove="handleDragMove"
      >
        &rarr;
      </div>
    </div>
    <!-- 刷新按钮 -->
    <div class="refresh" @click="onRefreshBtnClick"></div>
    <!-- 加载中提示 -->
    <div
      class="loading"
      v-show="isLoading"
      :style="{ width: `${width}px`, height: `${height}px` }"
    >
      <img
        src="https://img1.baidu.com/it/u=909624486,4182680343&fm=26&fmt=auto"
        alt=""
      />
      加载中...
    </div>
  </div>

然后定义一些支持婚恋app源码配置的属性

  props: {
    // 组件是否可见
    visiblity: {
      type: Boolean,
      default: false
    },
    // 组件的宽度
    width: {
      type: Number,
      default: 300
    },
    // 组件的高度
    height: {
      type: Number,
      default: 200
    },
    // 滑块的长度
    l: {
      type: Number,
      default: 42
    },
    // 滑块的半径
    r: {
      type: Number,
      default: 9
    },
    // 滑块的容错值
    tolerant: {
      type: Number,
      default: 5
    },
    // 成功时的回调
    onSuccess: {
      type: Function,
      default: () => {}
    },
    // 刷新时的回调
    onRefresh: {
      type: Function,
      default: () => {}
    },
    // 失败时的回调
    onFail: {
      type: Function,
      default: () => {}
    },
    // 关闭回调
    closed: {
      type: Function,
      default: () => {}
    }

3.实现镂空效果的图片

在这里插入图片描述
上图我们可以发现是一个不规则的图形,下面简单画一个草图
在这里插入图片描述
在开始之前,我们首先要了解用到的api:

  • beginPath(): 当你想创建一个新的路径时,调用此方法
  • moveTo(): 将一个新的子路径的起始点移动到(x,y)坐标的方法
  • arc(): 绘制圆弧路径的方法
  • lineTo(): 使用直线连接子路径的终点到x,y坐标的方法
  • stroke(): 描边
  • fill(): 填充
  • clip(): 裁剪
  • save():通过将当前状态放入栈中,保存 canvas 全部状态的方法。
  • restore():通过在绘图状态栈中弹出顶端的状态,将 canvas 恢复到最近的保存状态的方法。
  • getImageData():返回一个ImageData对象,用来描述canvas区域隐含的像素数据
  • putImageData():将数据从已有的 ImageData 对象绘制到位图的方法
  • drawImage():在canvas上绘制图像。

代码实现如下:

drawPath(x, y, l, r, ctx, operation) {
      ctx.beginPath();
      ctx.moveTo(x, y);
      ctx.arc(x + l / 2, y - r + 2, r, 0.72 * Math.PI, 2.26 * Math.PI);
      ctx.lineTo(x + l, y);
      ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * Math.PI, 2.78 * Math.PI);
      ctx.lineTo(x + l, y + l);
      ctx.lineTo(x, y + l);
      // anticlockwise为一个布尔值。为true时,是逆时针方向,否则顺时针方向
      ctx.arc(
        x + r - 2,
        y + l / 2,
        r + 0.4,
        2.76 * Math.PI,
        1.24 * Math.PI,
        true
      );
      ctx.lineTo(x, y);
      ctx.lineWidth = 2;
      ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
      ctx.strokeStyle = "rgba(255, 255, 255, 0.5)";
      ctx.stroke();
      ctx.globalCompositeOperation = "destination-over";
      // 判断是填充还是裁切, 裁切主要用于生成图案滑块
      operation === "fill" ? ctx.fill() : ctx.clip();
    }

通过该方法我们可以在canvas中画出对应的图案,细心的同学可以发现,我们在body中写了两个canvas标签,那么他们的作用分别是什么呢?

  • canvas-bg主要功能是绘制背景图片和镂空图案
  • block主要功能是对图案进行裁剪并进行移动

4、初始化函数

/**
     * 1. 随机获取到图片
     * 2. 随机生成图片滑块位置
     * 3. 截取图片并移动到初始位置
     * 4. 画出镂空图案
     * 5. 拿到下方滑块的初始位置
     */
    initCanvas() {
      // 拿到canvas对象
      let canvas = document.getElementsByClassName("canvas-bg")[0];
      let blockcanvas = document.getElementsByClassName("block")[0];
      // 画笔
      let ctx = canvas.getContext("2d");
      let blockCtx = blockcanvas.getContext("2d");
      // 每次重新绘制图片时,清除画布原有内容
      ctx.clearRect(0, 0, this.width, this.height);
      blockcanvas.width = this.width;
      // 生成image对象
      let img = new Image();
      // 解决跨域问题
      img.crossOrigin = "";
      img.onload = () => {
        ctx.drawImage(img, 0, 0);
        blockCtx.drawImage(img, 0, 0);
        this.isLoading = false;
        const ImageData = blockCtx.getImageData(x, y1, this.l + 2 * this.r, y);
        // 裁剪后重置画布的状态
        blockCtx.restore();
        blockcanvas.width = this.l + 2 * this.r;
        blockCtx.putImageData(ImageData, 0, y1);
      };
      // 图片访问地址,后面增加时间戳,防止拿缓存
      img.src = `https://picsum.photos/${this.width}/${
        this.height
      }?time=${+new Date()}`;
      // x y 位置随机
      let { x, y } = this.getXY();
      this.drawPath(x, y, this.l, this.r, ctx, "fill");
      // 裁剪前保存画布的状态
      blockCtx.save();
      this.drawPath(x, y, this.l, this.r, blockCtx, "clip");
      const y1 = y - this.r * 2 - 1;
    }

我们知道,婚恋app源码中滑动验证码的主要功能就是判断是否人为操作,我们通常采用的方式就是随机验证,这里我们前端采用Math.random()方法进行实现,更安全的做法是通过后端进行返回,生成随机位置的函数如下:

    // 随机生成滑块的目标位置
    getXY() {
      let x =
        this.width / 3 +
        Math.random() * ((this.width * 3) / 4 - this.width / 3);
      let y =
        this.height / 3 +
        Math.random() * ((this.height * 3) / 5 - this.height / 3);
      this.x = x;
      return { x, y };
    }

这里限制了位置坐标的范围,让滑块的目标位置更加的合理,让目标位置在白色区域范围内:
在这里插入图片描述
5.滑块的拖拽

完成以上代码后,页面布局基本为这个样子:
在这里插入图片描述
观察我们可以发现,我们拖拽下方箭头时,block跟随滑块移动即可,那么如何在婚恋app源码中实现一个滑块的拖拽呢?

我们可以想一下拖拽动作是如何发生的,按下鼠标左键后移动鼠标即可拖拽,鼠标释放完成拖拽,我们可以把它分解为三个动作:mousedown、mousemove、mouseup,我们监听三个动作即可完成相应的操作。

   handleDragMove(e) {
      if (!this.isDrop) return false;
      e.preventDefault();
      // 获取鼠标位置
      const eventX = e.clientX || e.touches[0].clientX;
      let moveX = eventX - this.blockInitLeft - 20;
      // 对滑块的位置进行风控处理
      if (moveX < 0 || moveX + 40 + 2 * this.r > this.width) return false;
      // 设置滑块的的位置及进度条的宽度
      this.blockLeft = moveX;
    },
    // 初始化未完成时,不可滑动
    // 滑动开始时,将状态置为等待状态
    handleDrapDown() {
      if (this.isLoading) return;
      this.isDrop = true;
      this.status = "wait";
    },
    // 拖拽动作完成之后执行
    handleDrapUp() {
      if (!this.isDrop) return;
      this.isDrop = false;
      // 判断是否拖拽的指定位置
      let val = Math.abs(this.x - this.blockLeft);
      this.status = val > this.tolerant ? "fail" : "success";
      // 执行相应的生命周期函数
      if (this.status === "fail") {
        this.onFail();
      } else {
        this.onSuccess();
      }
      // 1s后触发关闭回调或者刷新动作
      setTimeout(() => {
        if (this.status === "success" && this.visiblity) {
          this.closed();
          return;
        }
        this.handleRefresh();
      }, 1000);
    }

最后

婚恋app源码的滑块验证码组件大致功能已经完成,还有一些细节方面需要优化,希望以上内容能给大家带来帮助。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值