前端验证码实现

主体思路,使用canvas画布生成验证码,跟输入框内数据通过from表单进行对比

代码

//rules判断
rules: [{ validator: validateCode, trigger: 'change' }],
//validateCode方法内容

    validateCode(rule, value, callback) {
      if (value == '') {
        callback(new Error('验证码不能为空'))
      } else if (value !== this.identifyCode) {
        callback(new Error('验证码错误!'))
      } else {
        callback()
      }
    },



//组件化------验证码封装后的页面引入
<verificationPage :identifyCode="identifyCode" style="cursor: pointer" @click.native="getCode()" />

//date中要声明identifyCode这个变量,用于对比输入的值与验证码页面生成的验证码是否一致
      identifyCode: '',

//getCode方法触发验证码的生成与重新生成
//(这个方法在页面dom元素加载完时就需要调用一次,让验证码页面生成一个验证码)
    getCode() {
      var a = [
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        'a',
        'b',
        'c',
        'd',
        'e',
        'f',
        'g',
        'h',
        'i',
        'j',
        'k',
        'l',
        'm',
        'n',
        'o',
        'p',
        'q',
        'r',
        's',
        't',
        'u',
        'v',
        'w',
        'x',
        'y',
        'z',
      ]
      var code = ''
      for (var i = 0; i < 4; i++) {
        //0-1的随机小数 -->  0~数组长度-1的范围   取整
        var randPosition = Math.floor(Math.random() * (a.length - 1)) //每次生成一个随机数的位置
        code += a[randPosition] //带有随机位置作为下标,指示到当前随机产生的某个字符上,
      }
      this.identifyCode = code
    },

 验证码组件页面代码

<template>
  <div class="s-canvas" style="display: inline">
    <canvas
      id="s-canvas"
      :width="contentWidth"
      :height="contentHeight"
    ></canvas>
  </div>
</template>
  <script>
export default {
  name: "SIdentify",
  props: {
    identifyCode: {
      // 默认注册码
      type: String,
      default: "1234",
    },
    fontSizeMin: {
      // 字体最小值
      type: Number,
      default: 25,
    },
    fontSizeMax: {
      // 字体最大值
      type: Number,
      default: 35,
    },
    backgroundColorMin: {
      // 验证码图片背景色最小值
      type: Number,
      default: 200,
    },
    backgroundColorMax: {
      // 验证码图片背景色最大值
      type: Number,
      default: 220,
    },
    dotColorMin: {
      // 背景干扰点最小值
      type: Number,
      default: 60,
    },
    dotColorMax: {
      // 背景干扰点最大值
      type: Number,
      default: 120,
    },
    contentWidth: {
      // 容器宽度
      type: Number,
      default: 117,
    },
    contentHeight: {
      // 容器高度
      type: Number,
      default: 32,
    },
  },
  methods: {
    // 生成一个随机数
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },

    // 生成一个随机的颜色
    randomColor(min, max) {
      let r = this.randomNum(min, max);
      let g = this.randomNum(min, max);
      let b = this.randomNum(min, max);
      return "rgb(" + r + "," + g + "," + b + ")";
    },

    drawPic() {
      let canvas = document.getElementById("s-canvas");
      let ctx = canvas.getContext("2d");
      ctx.textBaseline = "bottom";
      // 绘制背景
      ctx.fillStyle = "#e6ecfd";
      ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
      // 绘制文字
      for (let i = 0; i < this.identifyCode.length; i++) {
        this.drawText(ctx, this.identifyCode[i], i);
      }
      this.drawLine(ctx);
      this.drawDot(ctx);
    },

    drawText(ctx, txt, i) {
      ctx.fillStyle = this.randomColor(50, 160); // 随机生成字体颜色
      ctx.font =
        this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei"; // 随机生成字体大小
      let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
      let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
      var deg = this.randomNum(-30, 30);
      // 修改坐标原点和旋转角度
      ctx.translate(x, y);
      ctx.rotate((deg * Math.PI) / 180);
      ctx.fillText(txt, 0, 0);
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180);
      ctx.translate(-x, -y);
    },

    drawLine(ctx) {
      // 绘制干扰线
      for (let i = 0; i < 4; i++) {
        ctx.strokeStyle = this.randomColor(100, 200);
        ctx.beginPath();
        ctx.moveTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.lineTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.stroke();
      }
    },

    drawDot(ctx) {
      // 绘制干扰点
      for (let i = 0; i < 30; i++) {
        ctx.fillStyle = this.randomColor(0, 255);
        ctx.beginPath();
        ctx.arc(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight),
          1,
          0,
          2 * Math.PI
        );
        ctx.fill();
      }
    },
  },
  watch: {
    identifyCode() {
      this.drawPic();
    },
  },
  mounted() {
    this.drawPic();
  },
};
</script>
  

### 如何在ElementUI中实现前端验证码 #### 使用 Vue 和 Element UI 创建图形验证码 为了实现前端显示并验证图形验证码,可以利用 `CaptchaUtil.createLineCaptcha` 方法来生成一个带有干扰线的图形验证码对象。此方法接受四个参数:宽度、高度、字符数量以及干扰线条数[^2]。 下面是一个完整的例子展示如何集成这个功能到基于 Vue.js 和 Element UI 的应用程序中: ```html <template> <div id="app"> <!-- 显示验证码 --> <img :src="captchaImage" @click="refreshCaptcha"/> <!-- 输入框 --> <el-input v-model="inputCode" placeholder="请输入验证码"></el-input> <!-- 提交按钮 --> <el-button type="primary" @click="submit">提交</el-button> </div> </template> <script> export default { data() { return { captcha: null, // 存储 Captcha 对象 inputCode: '', // 用户输入的验证码 captchaImage: '' // 验证码图片 URL }; }, methods: { createCaptcha() { this.captcha = window.CaptchaUtil.createLineCaptcha(80, 25, 4, 10); this.captchaImage = 'data:image/png;base64,' + this.captcha.getBase64Img(); }, refreshCaptcha() { this.createCaptcha(); // 刷新验证码 }, submit() { const userAnswer = this.inputCode.toLowerCase().trim(); if (this.captcha.check(userAnswer)) { alert('验证码正确'); } else { alert('验证码错误,请重试!'); this.refreshCaptcha(); // 错误则刷新验证码 } this.inputCode = ''; // 清空输入框 } }, mounted() { this.createCaptcha(); // 初始化时创建验证码 } }; </script> ``` 这段代码展示了如何通过点击事件触发验证码更新,并且当用户尝试提交表单时会检查他们输入的内容是否匹配当前显示的验证码。如果匹配,则提示成功;如果不符,则提醒重新输入并提供新的验证码图像。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值