需求:视频播放一段时间验证一下是否有人观看,弹框弹出验证码验证。
实现效果图:
实现:
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(); //每次点确定关闭弹窗更新验证码
}