vue3 canvas 自定义验证码组件

需求:视频播放一段时间验证一下是否有人观看,弹框弹出验证码验证。

实现效果图:

实现:

1.创建一个验证码组件。新建文件verification.vue

<template>
  <canvas
    id="captchaCanvas"
    @click="generateCaptcha"
    :style="{ width, height }"
  ></canvas>
</template>

<script setup>
import { watch, onMounted, toRefs } from "vue";
const emit = defineEmits(["getValue"]);
const props = defineProps({
  // 宽度
  width: {
    type: String,
    default: "100%",
  },
  // 高度
  height: {
    type: String,
    default: "100%",
  },
  //验证码数量
  number: {
    type: Number,
    default: 4,
  }, //验证码数量
  night: {
    type: Boolean,
    default: false,
  },
});
watch(
  () => props.night,
  () => {
    generateCaptcha();
  }
);
const generateCaptcha = () => {
  const canvas = document.getElementById("captchaCanvas");
  const ctx = canvas.getContext("2d");
  // 清除旧内容
  canvas.width = canvas.width;
  // 字符集
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let captchaText = "";
  // 设置背景颜色和一些基本样式
  ctx.fillStyle = props.night ? "#2d2c2c" : "#f9f9f9";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // 绘制噪点
  for (let i = 0; i < 200; i++) {
    ctx.fillStyle = getRandomColor(0, 300);
    ctx.fillRect(
      Math.random() * canvas.width,
      Math.random() * canvas.height,
      1,
      1
    );
  }
  // 绘制干扰线
  for (let i = 0; i < 9; i++) {
    ctx.strokeStyle = getRandomColor(150, 255);
    ctx.beginPath();
    ctx.moveTo(Math.random() * canvas.width, Math.random() * canvas.height);
    ctx.lineTo(Math.random() * canvas.width, Math.random() * canvas.height);
    ctx.stroke();
  }
  // 生成验证码文本
  for (let i = 0; i < props.number; i++) {
    // 假设验证码长度为 5
    const randomIndex = Math.floor(Math.random() * chars.length);
    const char = chars[randomIndex];
    captchaText += char;
    drawChar(
      char,
      1 + (i * canvas.width) / props.number,
      canvas.height / 2 + 20,
      70,
      getRandomColor(10, 50)
    );
  }
  //返回给父组件
  emit("getValue", captchaText);
};
const drawChar = (char, x, y, fontSize, fillStyle) => {
  const ctx = document.getElementById("captchaCanvas").getContext("2d");
  ctx.font = fontSize + "px Arial";
  ctx.fillStyle = fillStyle;
  ctx.fillText(char, x, y);
};

const getRandomColor = (min, max) => {
  var r = Math.floor(Math.random() * 256); // 0-255
  var g = Math.floor(Math.random() * 256);
  var b = Math.floor(Math.random() * 256);
  return `rgb(${r},${g},${b})`;
};
//暴露给父组件调用
defineExpose({ generateCaptcha });
onMounted(() => {
  generateCaptcha();
});
</script>

<style scoped>
#captchaCanvas {
  margin-bottom: 10px;
  display: block;
  user-select: none;
}
</style>

2.属性方法说明

属性/方法说明
width宽度(String),默认100%跟随父级宽度
height高度(String),默认100%跟随父级高度
number验证码个数(Number),默认4
night黑夜模式(Boolean),默认false
getValue(string)=>{},返回验证码值

3.页面中引入该组件

// 引入
import Captcha from "./verification.vue";

// 使用 template 部分
  <el-dialog
      v-model="verificationVisible"
      title="验证"
      width="600"
      class="zq-dialog-title-primary"
      append-to-body
      :showClose="false"
      :close-on-click-modal="false"
      align-center
    >
      <div style="display: flex; justify-content: center">
        <el-input
          v-model="verificationCode"
          style="width: 240px"
          placeholder="请输入"
        />
        <div style="width: 100px; height: 40px; margin-left: 20px">
          <Captcha ref="captchaRef" @getValue="getValue"></Captcha>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <!-- <el-button @click="onClose">取消</el-button> -->
          <el-button type="primary" @click="confirmCode"> 确定 </el-button>
        </div>
      </template>
    </el-dialog>


//使用 script部分
//获取验证码的值
const charCode = ref("");
const getValue = (val) => {
  console.log("验证码值=", val);
  charCode.value = val;
};
//这时候可以获取到验证码的值,但是验证码的值不会更新


//在需要更新验证码的地方调用组件抛出的方法generateCaptcha
const captchaRef = ref();
const confirmCode=()=>{
  captchaRef.value.generateCaptcha();  //每次点确定关闭弹窗更新验证码
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值