vue3.0实现炫酷的随机验证码功能
先上图
接下来楼一眼实现代码
这里说明一下,我用到了vue3.0,vant3.0以及阿里图标,vant 很人性化针对vue3.0新出了个vant3.0版本,阿里则是适配vue3.0的。我们将verify验证码进行了封装,内部用进行了hook以及工具的封装。
登录页代码 login.vue
<template> <div class="login"> <span class="iconfont icongouwuche"></span> <van-form @submit="onSubmit"> <van-field v-model="username" name="username" label="用户名" placeholder="用户名" :rules="[{ required: true, message: '请填写用户名' }]" /> <van-field v-model="password" type="password" name="password" label="密码" placeholder="密码" :rules="[{ required: true, message: '请填写密码' }]" /> <van-field center clearable label="验证码" placeholder="输入验证码" v-model="verify" > </van-field> <ImgVerify ref="verifyRef" /> <div style="margin: 16px"> <van-button round block color="#1baeae" native-type="submit"> 登录</van-button > </div> </van-form> </div> </template> <script> import { reactive, ref, toRefs } from "vue"; import ImgVerify from "@/components/ImgVerify"; export default { components: { ImgVerify }, setup(props, con) { const verifyRef = ref(null); const state = reactive({ username: "", password: "", verify: "", }); const onSubmit = (values) => { if (state.verify.toLowerCase() == verifyRef.value.imgCode.toLowerCase()) { // 提交时判断是否是正确验证码 alert("输入正确"); TODO; // } }; return { ...toRefs(state), onSubmit, verifyRef, }; }, }; </script> <style lang='scss' scoped> .login { /* background: #eee; */ } div { font-size: 14px; .icongouwuche { padding-top: 40px; font-size: 120px; } } </style>
验证码组件 ImgVerify.vue
这里只是简单地获取以及排版,正正的逻辑放到了hook中
<template> <div> <canvas ref="verify" :width="width" :height="height" @click="handleDraw" ></canvas> </div> </template> <script> import {ref } from "vue"; import {setVerify} from '../hooks/Verify' export default { setup(props, con) { const verify = ref(null); return{ ...setVerify(verify) } }, }; </script> <style lang='scss' scoped> </style>
我们先看一下封装好的tool工具函数。
Tool.js
//随机数 export function randomNum(min, max) { return parseInt(Math.random() * (max - min + 1) + min); }; //随机颜色 export function randomColor(min, max) { const r = randomNum(min, max); const g = randomNum(min, max); const b = randomNum(min, max); return `rgb(${r},${g},${b})`; };
接下来重头戏实现验证码
verify.js
import { onMounted, toRefs, reactive } from "vue"; import { randomColor, randomNum } from '../utils/Tools' export function setVerify(verify) { const state = reactive({ pool: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", // 随机字符串 width: 120, //展示区域宽度 height: 40, //展示区域高度 imgCode: "", //保存页面的内容(用来判断输入验证是否满足改code) }); // 1、初始展示 onMounted(() => { draw(); state.imgCode = draw(); }); // 2、点击图片重新绘制 const handleDraw = () => { draw(); state.imgCode = draw(); }; // 3、绘制随机内容 const draw = () => { /* * 一、填充颜色 * 1、生成画布 * 2、填充颜色与位置 * 3、填充位置 */ const ctx = verify.value.getContext("2d"); ctx.fillStyle = randomColor(180, 230); ctx.fillRect(0, 0, state.width, state.height); /* * 二、生成4个随机数 * 1、七扭八歪 * 2、随机大小 * 3、画吧柳梢,各种色儿 */ let imgCode = ""; for (let i = 0; i < 4; i++) { const text = state.pool[randomNum(0, state.pool.length - 1)]; const fontSize = randomNum(18, 40); const deg = randomNum(-30, 30); /* * 绘制文字并让四个文字在不同的位置显示的思路 : * 1、定义字体 * 2、定义对齐方式 * 3、填充不同的颜色 * 4、保存当前的状态(以防止以上的状态受影响) * 5、平移translate() * 6、旋转 rotate() * 7、填充文字 * 8、restore出栈 * */ ctx.font = fontSize + "px Simhei"; ctx.textBaseline = "top"; ctx.fillStyle = randomColor(80, 150);
ctx.save(); ctx.translate(30 * i + 15, 15); ctx.rotate((deg * Math.PI) / 180); ctx.fillText(text, -15 + 5, -15); ctx.restore(); imgCode += text; } /* * 三、随机产生5条干扰线,干扰线的颜色要浅一点 */ for (let i = 0; i < 5; i++) { ctx.beginPath(); ctx.moveTo(randomNum(0, state.width), randomNum(0, state.height)); ctx.lineTo(randomNum(0, state.width), randomNum(0, state.height)); ctx.strokeStyle = randomColor(180, 230); ctx.closePath(); ctx.stroke(); } /* * 四、随机产生40个干扰的小点 */ for (let i = 0; i < 40; i++) { ctx.beginPath(); ctx.arc( randomNum(0, state.width), randomNum(0, state.height), 1, 0, 2 * Math.PI ); ctx.closePath(); ctx.fillStyle = randomColor(150, 200); ctx.fill(); } return imgCode; }; return { ...toRefs(state), handleDraw, verify, }; }
一个vscode快熟生成vue3代码片段的方法
1、选择 文件---》首选项---》代码片段---》
2、新建json
3、配置json
"Print to console": { "prefix": "vue3", "body": [ "<template>", "<div>", "", "</div>", "</template>", "", "<script>", "export default {", " components: {},", " setup(props,con){}", "}", "</script>", "", "<style lang='scss' scoped>", "", "</style>", "$2" ], "description": "Vue3模板" }