【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>
相关推荐
m0_748251086 分钟前
docker安装nginx,docker部署vue前端,以及docker部署java的jar部署
java·前端·docker
我是ed18 分钟前
# thingjs 基础案例整理
前端
Ashore_25 分钟前
从简单封装到数据响应:Vue如何引领开发新模式❓❗️
前端·vue.js
落魄实习生27 分钟前
小米路由器开启SSH,配置阿里云ddns,开启外网访问SSH和WEB管理界面
前端·阿里云·ssh
顽疲29 分钟前
从零用java实现 小红书 springboot vue uniapp (6)用户登录鉴权及发布笔记
java·vue.js·spring boot·uni-app
bug丸35 分钟前
v8引擎垃圾回收
前端·javascript·垃圾回收
安全小王子36 分钟前
攻防世界web第三题file_include
前端
&活在当下&38 分钟前
ref 和 reactive 的用法和区别
前端·javascript·vue.js
百事老饼干41 分钟前
VUE前端实现防抖节流 Lodash
前端
web Rookie1 小时前
React 高阶组件(HOC)
前端·javascript·react.js