<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>图形验证码示例</title> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f5f5f5; margin: 0; } .container { background: white; padding: 20px 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); text-align: center; } canvas { border: 1px solid #ccc; cursor: pointer; margin-top: 10px; } input[type="text"] { padding: 8px; margin-top: 10px; width: 120px; text-align: center; border: 1px solid #ccc; border-radius: 4px; } button { margin-top: 15px; padding: 8px 16px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #0056b3; } .message { margin-top: 10px; font-size: 14px; color: #d9534f; } </style> </head> <body> <div class="container"> <h3>请输入验证码</h3> <canvas id="captchaCanvas" width="120" height="40"></canvas> <br /> <input type="text" id="userInput" maxlength="4" placeholder="输入验证码" autocomplete="off" /> <br /> <button onclick="validateCaptcha()">验证</button> <div id="message" class="message"></div> </div> <script> let captchaCode = ''; // 生成随机验证码 function generateCaptcha() { const chars = 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789'; let result = ''; for (let i = 0; i < 4; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } // 绘制验证码到 Canvas function drawCaptcha() { const canvas = document.getElementById('captchaCanvas'); const ctx = canvas.getContext('2d'); captchaCode = generateCaptcha(); // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 背景色 ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 干扰线 for (let i = 0; i < 5; i++) { ctx.strokeStyle = `rgb(${Math.floor(Math.random() * 100)}, ${Math.floor(Math.random() * 100)}, ${Math.floor(Math.random() * 100)})`; ctx.beginPath(); ctx.moveTo(Math.random() * canvas.width, Math.random() * canvas.height); ctx.lineTo(Math.random() * canvas.width, Math.random() * canvas.height); ctx.stroke(); } // 验证码文字 ctx.font = 'bold 24px Arial'; ctx.textBaseline = 'middle'; for (let i = 0; i < captchaCode.length; i++) { ctx.fillStyle = `rgb(${Math.floor(Math.random() * 100 + 100)}, ${Math.floor(Math.random() * 100 + 100)}, ${Math.floor(Math.random() * 100 + 100)})`; const x = 10 + i * 25; const y = canvas.height / 2 + (Math.random() - 0.5) * 10; ctx.save(); ctx.translate(x, y); ctx.rotate((Math.random() - 0.5) * 0.5); // 轻微旋转 ctx.fillText(captchaCode[i], 0, 0); ctx.restore(); } // 干扰点 for (let i = 0; i < 30; i++) { ctx.fillStyle = `rgb(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)})`; ctx.beginPath(); ctx.arc(Math.random() * canvas.width, Math.random() * canvas.height, 1, 0, 2 * Math.PI); ctx.fill(); } } // 刷新验证码(点击 Canvas) document.getElementById('captchaCanvas').addEventListener('click', drawCaptcha); // 验证用户输入 function validateCaptcha() { const userInput = document.getElementById('userInput').value.trim(); const messageEl = document.getElementById('message'); if (userInput === '') { messageEl.textContent = '请输入验证码!'; return; } if (userInput.toLowerCase() === captchaCode.toLowerCase()) { messageEl.style.color = '#28a745'; messageEl.textContent = '验证成功!'; // 可在此处提交表单或执行其他操作 } else { messageEl.style.color = '#d9534f'; messageEl.textContent = '验证码错误,请重试!'; drawCaptcha(); // 验证失败自动刷新 document.getElementById('userInput').value = ''; } } // 页面加载时生成验证码 window.onload = drawCaptcha; </script> </body> </html>图形验证码示例
张小明
前端开发工程师
GPT-SoVITS语音合成静音处理:避免空白段落输出
GPT-SoVITS语音合成静音处理:避免空白段落输出 在当前AI内容爆发的时代,个性化语音合成正从实验室走向千行百业。无论是短视频配音、智能音箱播报,还是数字人对话系统,用户对“像真人”的语音输出提出了更高要求——不仅要音色逼真…
GPT-SoVITS支持实时推理吗?WebSocket接口实现方案
GPT-SoVITS支持实时推理吗?WebSocket接口实现方案 在虚拟主播直播间里,观众刚打出一句提问,几秒钟后屏幕上的数字人便用“原声级”音色自然回应——这种看似科幻的交互,正逐渐成为现实。然而,支撑这一体验的背后&#…
JLink烧录器使用教程:解决工控环境中下载失败的核心要点
JLink烧录器实战指南:工控现场下载失败的根源与破局之道在工业控制设备的开发和维护中,程序烧录本应是一个“点一下就能完成”的常规操作。但现实却常常事与愿违——你坐在电磁干扰强烈的配电柜旁,手握J-Link,面对满屏的“Target …
不同类型电动汽车充电负荷蒙特卡洛法模拟(常规充电、快速充电、更换电池)(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…
突破语言壁垒:XUnity自动翻译插件实战指南
突破语言壁垒:XUnity自动翻译插件实战指南 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为看不懂日文游戏剧情而烦恼吗?是否曾经因为语言障碍错过了无数精彩的游戏内容&…
STM32CubeMX下载后无法打开?深度剖析原因与修复
STM32CubeMX 下载后打不开?别急,一文彻底解决启动难题 你是不是也遇到过这种情况:好不容易按照“ stm32cubemx 下载教程 ”一步步安装完软件,双击图标却毫无反应——没弹窗、无报错、任务管理器里闪现一下 java.exe 又消失……