-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
122 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Graphical CAPTCHA</title> | ||
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@700&display=swap" rel="stylesheet"> | ||
<style> | ||
#captcha { | ||
border: 1px solid #ccc; | ||
display: inline-block; | ||
margin-bottom: 10px; | ||
} | ||
#captcha-container { | ||
margin-bottom: 10px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="captcha-container"> | ||
<canvas id="captcha" width="200" height="50"></canvas> | ||
</div> | ||
<input type="text" id="captcha-input" placeholder="Enter CAPTCHA"> | ||
<button onclick="validateCaptcha()">Validate</button> | ||
<p id="result"></p> | ||
|
||
<script> | ||
let captchaText = ''; | ||
|
||
function generateCaptcha() { | ||
const canvas = document.getElementById('captcha'); | ||
const ctx = canvas.getContext('2d'); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
|
||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
captchaText = ''; | ||
for (let i = 0; i < 6; i++) { | ||
captchaText += chars.charAt(Math.floor(Math.random() * chars.length)); | ||
} | ||
|
||
for (let layer = 0; layer < 5; layer++) { | ||
const opacity = 1 - layer * 0.2; | ||
ctx.globalAlpha = opacity; | ||
|
||
// 绘制背景图案 | ||
for (let i = 0; i < 20; 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 < 200; i++) { | ||
ctx.fillStyle = getRandomColor(); | ||
ctx.fillRect(Math.random() * canvas.width, Math.random() * canvas.height, 2, 2); | ||
} | ||
|
||
// 绘制验证码文本 | ||
ctx.font = '30px "Dancing Script"'; | ||
ctx.textBaseline = 'middle'; // 确保文本垂直居中 | ||
for (let i = 0; i < captchaText.length; i++) { | ||
ctx.save(); | ||
ctx.fillStyle = getRandomColor(); | ||
const x = 10 + i * 30; | ||
const y = canvas.height / 2 + Math.random() * 10 - 5; // 确保文本垂直居中 | ||
const angle = Math.random() * 2 * Math.PI; // 随机旋转角度 | ||
ctx.translate(x, y); | ||
ctx.rotate(angle); | ||
ctx.fillText(captchaText.charAt(i), 0, 0); | ||
ctx.restore(); | ||
} | ||
} | ||
|
||
// 添加更强的扭曲效果 | ||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
const data = imageData.data; | ||
for (let i = 0; i < data.length; i += 4) { | ||
const dx = Math.sin(i / 30) * 10; | ||
const dy = Math.cos(i / 30) * 10; | ||
const srcX = (i / 4) % canvas.width; | ||
const srcY = Math.floor((i / 4) / canvas.width); | ||
const destX = Math.min(canvas.width - 1, Math.max(0, srcX + dx)); | ||
const destY = Math.min(canvas.height - 1, Math.max(0, srcY + dy)); | ||
const destIndex = (destY * canvas.width + destX) * 4; | ||
data[destIndex] = data[i]; | ||
data[destIndex + 1] = data[i + 1]; | ||
data[destIndex + 2] = data[i + 2]; | ||
data[destIndex + 3] = data[i + 3]; | ||
} | ||
ctx.putImageData(imageData, 0, 0); | ||
} | ||
|
||
function getRandomColor() { | ||
const letters = '0123456789ABCDEF'; | ||
let color = '#'; | ||
for (let i = 0; i < 6; i++) { | ||
color += letters[Math.floor(Math.random() * 16)]; | ||
} | ||
return color; | ||
} | ||
|
||
function validateCaptcha() { | ||
const input = document.getElementById('captcha-input').value; | ||
const result = document.getElementById('result'); | ||
if (input === captchaText) { | ||
result.textContent = 'CAPTCHA validated successfully!'; | ||
result.style.color = 'green'; | ||
} else { | ||
result.textContent = 'CAPTCHA validation failed. Please try again.'; | ||
result.style.color = 'red'; | ||
} | ||
} | ||
|
||
generateCaptcha(); | ||
</script> | ||
</body> | ||
</html> |