前端生成绘制一个验证码,并验证

本文介绍了如何使用前端技术,特别是vantUI库和canvas,实现一个可自定义的验证码组件。开发者展示了如何在弹窗中生成随机字母验证码,并在用户输入后进行验证,同时提及了与后端接口交互的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上效果:

这里是前端生成的验证码,如果需要请求后端把随机数改为接口就好了。

使用的是vantUI的弹窗,当然核心还是canvas。我将它封装成组件了直接上代码:

<template>
  <div class="component">
    <van-dialog
      ref="dialog"
      v-model="showDialog"
      title="请输入验证码"
      :before-close="onBeforeClose"
    >
      <canvas ref="canvas" :width="width" :height="height" />
      <van-field
        style="margin-top: 20px"
        v-model="decode"
        label="验证码:"
        placeholder="请输入验证码"
      />
    </van-dialog>
  </div>
</template>

<script>
import { Notify } from "vant";
export default {
  props: {
    width: {
      type: Number,
      default: 200,
    },
    height: {
      type: Number,
      default: 50,
    },
    length: {
      // 生成长度
      type: Number,
      default: 4,
    },
    fontSize: {
      type: Number,
      default: 30,
    },
  },
  data() {
    return {
      showDialog: false,
      decode: "",
      encode: "",
    };
  },
  watch: {
    showDialog(newVal, oldVal) {
      if (newVal) {
        this.$nextTick(() => {
          this.drawCaptcha();
        });
      }
    },
  },
  mounted() {},
  methods: {
    async onBeforeClose(action, done) {
      if (action === "confirm") {
        // 点击确定走这里
        if (this.encode == this.decode.toUpperCase()) {
          done(); // 关闭弹窗
          this.decode = "";
        } else {
          Notify("验证码错误!");
          return done(false); // 阻止弹窗关闭
        }
      } else {
        done(); // 关闭弹窗
      }
    },
    drawCaptcha() {
      const canvas = this.$refs.canvas;
      const context = canvas.getContext("2d");
      // 清除画布
      context.clearRect(0, 0, this.width, this.height);
      // 计算字符之间的间距
      const spacing = this.width / (this.length + 1);
      // 随机生成指定长度的大写字母验证码
      const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      // 验证码
      this.encode = "";
      for (let i = 0; i < this.length; i++) {
        const randomLetter =
          alphabet[Math.floor(Math.random() * alphabet.length)];
        this.encode += randomLetter;
        // 设置字体和样式
        context.font = `bold ${this.fontSize}px Arial`;
        context.fillStyle = "#000";
        // 随机旋转角度
        const angle = Math.random() * 1 - 0.2;
        // 平移画布以便绘制倾斜的字符,并应用间距
        context.translate((i + 1) * spacing, this.height / 2);
        context.rotate(angle);
        // 在画布上绘制验证码
        context.fillText(randomLetter, -12, 12);
        // 恢复画布状态,以便绘制下一个字符
        context.rotate(-angle);
        context.translate(-((i + 1) * spacing), -(this.height / 2));
      }

      // 添加干扰元素
      for (let i = 0; i < (this.width * this.height) / 100; i++) {
        const x1 = Math.random() * this.width;
        const y1 = Math.random() * this.height;
        const lengthFactor = Math.random() * 20; // 控制线的长度范围
        const x2 = x1 + Math.cos(Math.random() * Math.PI * 2) * lengthFactor;
        const y2 = y1 + Math.sin(Math.random() * Math.PI * 2) * lengthFactor;
        // 生成线
        context.strokeStyle = this.getRandomColor();
        context.lineWidth = 1;
        context.beginPath();
        context.moveTo(x1, y1);
        context.lineTo(x2, y2);
        context.stroke();
        // 生成点
        const x = Math.random() * this.width;
        const y = Math.random() * this.height;
        context.fillStyle = this.getRandomColor();
        context.fillRect(x, y, 1, 1);
      }
    },
    getRandomColor() {
      const letters = "0123456789ABCDEF";
      let color = "#";

      for (let i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
      }

      return color;
    },
  },
};
</script>

<style scoped lang="scss">
</style>

调用:

<DialogCode ref="dialogCode" />
// 调用
  methods: {
    showCode() {
      this.$refs.dialogCode.showDialog = true;
    },
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值