验证码组件
captcha.vue
<template>
<div class="captcha-container">
<canvas ref="canvas" :width="canvasWidth" :height="canvasHeight" @click="generateCaptcha"></canvas>
</div>
</template>
<script>
export default {
data() {
return {
captchaText: '', // 验证码文本
canvasWidth: 100,
canvasHeight: 50
};
},
mounted() {
this.generateCaptcha(); // 初始化生成验证码
},
methods: {
// 生成随机验证码
generateCaptcha() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
this.captchaText = Array.from({ length: 4 })
.map(() => chars[Math.floor(Math.random() * chars.length)])
.join('');
this.drawCaptcha();
this.$emit('input', this.captchaText);
this.$emit('onChange', this.captchaText);
},
// 绘制验证码到 Canvas
drawCaptcha() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
// 清空画布
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// 绘制背景
ctx.fillStyle = '#f4f4f4';
ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
// 添加一些干扰线
for (let i = 0; i < 5; i++) {
ctx.strokeStyle = this.getRandomColor();
ctx.beginPath();
ctx.moveTo(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight);
ctx.lineTo(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight);
ctx.stroke();
}
// 绘制验证码文字
ctx.font = '30px Arial';
ctx.fillStyle = this.getRandomColor();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const charArray = this.captchaText.split('');
charArray.forEach((char, index) => {
const x = (this.canvasWidth / charArray.length) * (index + 0.5);
const y = this.canvasHeight / 2;
const angle = (Math.random() - 0.5) * 30; // 随机旋转角度
ctx.save();
ctx.translate(x, y);
ctx.rotate((angle * Math.PI) / 180);
ctx.fillText(char, 0, 0);
ctx.restore();
});
// 添加一些干扰点
for (let i = 0; i < 50; i++) {
ctx.fillStyle = this.getRandomColor();
ctx.beginPath();
ctx.arc(Math.random() * this.canvasWidth, Math.random() * this.canvasHeight, 1, 0, 2 * Math.PI);
ctx.fill();
}
console.log(this.captchaText);
},
// 生成随机颜色
getRandomColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r},${g},${b})`;
}
}
};
</script>
<style scoped>
.captcha-container {
display: flex;
align-items: center;
gap: 10px;
}
canvas {
border: 1px solid #ccc;
}
</style>
使用和验证
// yzmCode 生成的验证码
<CaptchaCode v-model="yzmCode" ref="CaptchaCodeRef" style="margin-left: 10px" @onChange="yzm = ''" />
// 验证(字母转大写)
// yzm 输入的验证码
if (this.yzm.toUpperCase() != this.yzmCode.toUpperCase()) {
this.$refs.CaptchaCodeRef.generateCaptcha();
return this.$message.error('请输入正确的验证码');
}
效果图