在您的Vue项目中,是否曾遇到过需要增加验证码来增强账户安全性的情况?这个Vue通用Canvas验证码组件!采用Canvas,实现了高度自定义和灵活的验证码生成方式,让您的网站或应用轻松应对各类验证码需求。
在线演示地址: 验证码演示
<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++) {
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>
<template>
<div style="width: 200px;height: 80px">
<Captcha ref="captchaRef" @getValue="getValue" ></Captcha>
</div>
</template>
<script setup>
import Captcha from '../components/Captcha.vue';
const getValue=(val)=>{
console.log('验证码值=',val)
}
</script>
<style >
body{
display: flex;
justify-content: center;
}
</style>
属性名称 | 说明 |
---|---|
width | 宽度(String),默认100%跟随父级宽度 |
height | 高度(String),默认100%跟随父级高度 |
number | 验证码个数(Number),默认4 |
night | 黑夜模式(Boolean),默认false |
方法名称 | 说明 |
---|---|
getValue | (string)=>{},返回验证码值 |