【vue】vue前端实现随机验证码(数字、字母混合)功能

效果图:使用canvas组件对随机的数字字母添加插画背景、干扰线、干扰点

1、在components文件夹下新建securityCode.vue文件,代码:

js 复制代码
<template>
	<canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
</template>
<script>
	export default {
		name: "securityCode",
		props: {
			identifyCode: {
				type: String,
				default: "",
			},
			fontSizeMin: {
				type: Number,
				default: 22,
			},
			fontSizeMax: {
				type: Number,
				default: 40,
			},
			backgroundColorMin: {
				type: Number,
				default: 180,
			},
			backgroundColorMax: {
				type: Number,
				default: 240,
			},
			colorMin: {
				type: Number,
				default: 50,
			},
			colorMax: {
				type: Number,
				default: 160,
			},
			lineColorMin: {
				type: Number,
				default: 40,
			},
			lineColorMax: {
				type: Number,
				default: 180,
			},
			dotColorMin: {
				type: Number,
				default: 0,
			},
			dotColorMax: {
				type: Number,
				default: 255,
			},
			contentWidth: {
				type: Number,
				default: 120,
			},
			contentHeight: {
				type: Number,
				default: 40,
			},
		},
		methods: {
			// 生成一个随机数
			randomNum(min, max) {
				return Math.floor(Math.random() * (max - min) + min);
			},
			// 生成一个随机的颜色
			randomColor(min, max) {
				let r = this.randomNum(min, max);
				let g = this.randomNum(min, max);
				let b = this.randomNum(min, max);
				return "rgb(" + r + "," + g + "," + b + ")";
			},
			drawPic() {
				let canvas = document.getElementById("s-canvas");
				let ctx = canvas.getContext("2d");
				ctx.textBaseline = "bottom";
				// 绘制背景
				ctx.fillStyle = this.randomColor(
					this.backgroundColorMin,
					this.backgroundColorMax
				);
				ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
				// 绘制文字
				for (let i = 0; i < this.identifyCode.length; i++) {
					this.drawText(ctx, this.identifyCode[i], i);
				}
				this.drawLine(ctx);
				this.drawDot(ctx);
			},
			drawText(ctx, txt, i) {
				ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax);
				ctx.font =
					this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei";
				let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
				let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
				var deg = this.randomNum(-45, 45);
				// 修改坐标原点和旋转角度
				ctx.translate(x, y);
				ctx.rotate((deg * Math.PI) / 330);
				ctx.fillText(txt, 0, 0);
				// 恢复坐标原点和旋转角度
				ctx.rotate((-deg * Math.PI) / 330);
				ctx.translate(-x, -y);
			},
			drawLine(ctx) {
				// 绘制干扰线
				for (let i = 0; i < 3; i++) {
					ctx.strokeStyle = this.randomColor(
						this.lineColorMin,
						this.lineColorMax
					);
					ctx.beginPath();
					ctx.moveTo(
						this.randomNum(0, this.contentWidth),
						this.randomNum(0, this.contentHeight)
					);
					ctx.lineTo(
						this.randomNum(0, this.contentWidth),
						this.randomNum(0, this.contentHeight)
					);
					ctx.stroke();
				}
			},
			drawDot(ctx) {
				// 绘制干扰点
				for (let i = 0; i < 80; i++) {
					ctx.fillStyle = this.randomColor(0, 255);
					ctx.beginPath();
					ctx.arc(
						this.randomNum(0, this.contentWidth),
						this.randomNum(0, this.contentHeight),
						1,
						0,
						2 * Math.PI
					);
					ctx.fill();
				}
			},
		},
		watch: {
			identifyCode() {
				this.drawPic();
			},
		},
		mounted() {
			this.drawPic();
		},
	};
</script>

2、在登录页面引入并注册使用组件:

html 复制代码
<el-form-item prop="pass" label="验证码" class="row" label-width="150px">
	<div class="row space-between" style="width: 315px;">
		<el-input type="text" style="width: 190px;" v-model="inputCode" autocomplete="off"></el-input>
		<div @click="refreshCode()" style="line-height: 0;">
			<!--验证码组件-->
			<SecurityCode :identifyCode="identifyCode"></SecurityCode>
		</div>
	</div>
</el-form-item>
<el-form-item style="padding-left: 55px;">
	<el-button type="primary" @click="submitForm()" icon="el-icon-s-custom">
		<span style="font-size: 15px;letter-spacing: 10px;">登录</span>
	</el-button>
</el-form-item>
js 复制代码
<script>
	//导入组件
	import SecurityCode from "@/components/securityCode";
	export default {
		components: {//注册
			SecurityCode
		},
        data() {
            identifyCode: "",//随机组合字符串
			inputCode: "", //text框输入的验证码
        },
        mounted() {
			this.refreshCode();
		},
        methods: {
			//初始化验证码
			refreshCode() {
				this.inputCode = ''
				this.identifyCode = ""; //输入框置空
				this.makeCode(4); //验证码长度为4
			},
			//随机切换验证码
			makeCode(length) {
				let code = '';
				for (let i = 0; i < length; i++) {
					const r = Math.floor(Math.random() * 36);
					if (r < 10) {
						code += r;
					} else {
						code += String.fromCharCode(r - 10 + 65);
					}
				}
				this.identifyCode = code
				localStorage.setItem('code', code);
				console.log(this.identifyCode);
			},
            submitForm(formName) {
				const code = this.inputCode.toLowerCase();
				const originalCode = localStorage.getItem('code').toLowerCase();
				if (!code) {
					this.$message.error('请输入验证码!');
					return
				} else if (code !== originalCode) {
					this.$message.error('验证码输入错误!');
					this.refreshCode()
					return
				}
				// this.$api.Login({
				// 	userName: this.ruleForm.user,
				// 	password: this.ruleForm.pass,
				// 	systemCode: null,
				// }).then((data) => {
				// })
			},
        }
    }
</script>
相关推荐
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果5 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄6 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰6 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询