当前位置: 首页 > news >正文

vue - 使用canvas绘制验证码

封装绘制验证码 verify-code.vue

<template><div class="captcha"><canvas ref="canvasRef" :width="width" :height="height" @click="refreshCaptcha"></canvas></div>
</template><script lang="ts" setup>const props = defineProps({width: {type: Number,default: 120,},height: {type: Number,default: 40,},codeLength: {type: Number,default: 5,},})const captchaText = ref('')const canvasRef = ref()onMounted(() => {refreshCaptcha()})const emits = defineEmits(['getCode'])const generateRandomText = () => {const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'let result = ''for (let i = 0; i < props.codeLength; i++) {result += chars.charAt(Math.floor(Math.random() * chars.length))}return result}const refreshCaptcha = () => {captchaText.value = generateRandomText()drawCaptcha()emits('getCode', captchaText.value)}const drawCaptcha = () => {const canvas = canvasRef.valueconst ctx = canvas.getContext('2d')// 清除画布ctx.clearRect(0, 0, canvas.width, canvas.height)// 背景色ctx.fillStyle = '#f5f5f5'ctx.fillRect(0, 0, canvas.width, canvas.height)// 绘制文字ctx.font = '20px Arial'ctx.fillStyle = '#333'ctx.textAlign = 'center'ctx.textBaseline = 'middle'// 添加干扰线for (let i = 0; i < 5; i++) {ctx.strokeStyle = getRandomColor()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 < 30; i++) {ctx.fillStyle = getRandomColor()ctx.fillRect(Math.random() * canvas.width, Math.random() * canvas.height, 2, 2)}// 绘制文字(每个字符单独处理以增加变形)for (let i = 0; i < captchaText.value.length; i++) {ctx.save()ctx.translate(10 + i * 16, 16)ctx.rotate((Math.random() - 0.5) * 0.4)ctx.fillText(captchaText.value[i], 0, 0)ctx.restore()}}const getRandomColor = () => {const letters = '0123456789ABCDEF'let color = '#'for (let i = 0; i < 6; i++) {color += letters[Math.floor(Math.random() * 16)]}return color}defineExpose({code: captchaText,refresh: refreshCaptcha,})
</script><style>.captcha canvas {cursor: pointer;}
</style>

使用

<template><div><el-input v-model="input" placeholder="" style="width: 100px;"></el-input><VueVerifyCoderef="verifyCodeRef":width="74":height="34":code-length="4"style="margin-left: 8px;border: 1px solid var(--color-border-2);padding: 0 2px;"@get-code="getCode"/><el-button type="primary" @click="submit">登录</el-button></div>
</template><script lang="ts" setup>
import VueVerifyCode from "@/components/verify-code.vue";
const verifyCodeRef = ref();
const input = ref(""); //输入的验证码
const verifyCode = ref(""); //当前验证码
//获取当前验证码
const getCode = (code: string) => {verifyCode.value = code;
};
const submit = ()=>{//判断验证码是否相同 全部转换为小写if (input.value.toLocaleLowerCase() !== verifyCode.value.toLocaleLowerCase()) {alert('验证码错误!')verifyCodeRef.value.refresh()return}
}
</script><style lang="sass" scoped></style>

http://www.lryc.cn/news/599689.html

相关文章:

  • 容器化环境下的服务器性能瓶颈与优化策略
  • Linux 中 `chown`、`chgrp` 和 `chmod` 命令详解
  • MRDIMM对服务器总体拥有成本(TCO)影响的系统性分析
  • openmv识别数字
  • 8.异常处理:优雅地处理错误
  • java面试题(二)
  • Java面试题及详细答案120道之(001-020)
  • [Rust 基础课程]猜数字游戏-获取用户输入并打印
  • 不用电脑要不要关机?
  • 【Spring WebFlux】为什么 Spring 要拥抱响应式
  • OT82111_VC1:USB OTG音频解码器固件技术解析
  • c++注意点(12)----设计模式(生成器)
  • Promise的allSettled,all,race
  • 智能网关:物联网时代的核心枢纽
  • 在OpenMP中,#pragma omp的使用
  • 【Linux/Ubuntu】VIM指令大全
  • 如何搭建Linux环境下的flink本地集群
  • 为什么选择EasyGBS?
  • 《解锁前端数据持久化与高效查询:IndexedDB深度剖析》
  • vue3单页面连接多个websocket并实现断线重连功能
  • TDengine 转化函数 TO_TIMESTAMP 用户手册
  • 比特币技术简史 第八章:扩展性解决方案 - 闪电网络与隔离见证
  • 软件工程:软件需求
  • Ethereum:告别 personal API,拥抱 Geth 的独立签名器 Clef
  • CRM 系统:实现商机全流程管理的关键
  • Mkdocs相关插件推荐(原创+合作)
  • 力扣Hot100疑难杂症汇总
  • Java环境配置之各类组件下载安装教程整理(jdk、idea、git、maven、mysql、redis)
  • 如何序列化和反序列化动态 XmlElement ?
  • 【SSL证书校验问题】通过 monkey-patch 关掉 SSL 证书校验