Created
August 14, 2025 23:37
-
-
Save aschmelyun/949b3d87dd9c8ad579a9a2fd06794f7e to your computer and use it in GitHub Desktop.
lizard.click source code
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
<meta name="theme-color" content="#ffffff"> | |
<meta name="apple-mobile-web-app-capable" content="yes"> | |
<meta name="apple-mobile-web-app-status-bar-style" content="default"> | |
<meta name="apple-mobile-web-app-title" content="Lizard"> | |
<title>Lizard</title> | |
<style> | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
min-height: 60vh; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
background: #f0f0f0; | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; | |
} | |
.button-3d { | |
width: 200px; | |
height: 200px; | |
background: #ffffff; | |
border: none; | |
border-radius: 50%; | |
cursor: pointer; | |
font-size: 80px; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
touch-action: manipulation; | |
box-shadow: | |
0 10px 20px rgba(0, 0, 0, 0.2), | |
0 6px 10px rgba(0, 0, 0, 0.15), | |
inset 0 -3px 0 rgba(0, 0, 0, 0.1); | |
} | |
.button-3d:hover { | |
box-shadow: | |
0 12px 24px rgba(0, 0, 0, 0.2), | |
0 8px 12px rgba(0, 0, 0, 0.15), | |
inset 0 -3px 0 rgba(0, 0, 0, 0.1); | |
} | |
.button-3d:active { | |
transform: translateY(4px); | |
box-shadow: | |
0 4px 8px rgba(0, 0, 0, 0.2), | |
0 2px 4px rgba(0, 0, 0, 0.15), | |
inset 0 -1px 0 rgba(0, 0, 0, 0.1); | |
} | |
.emoji { | |
user-select: none; | |
} | |
.animated-emoji { | |
position: fixed; | |
font-size: 40px; | |
pointer-events: none; | |
z-index: 1000; | |
opacity: 0; | |
user-select: none; | |
} | |
@keyframes emojiPop { | |
0% { | |
opacity: 0; | |
transform: translateY(100px) scale(0.5); | |
} | |
20% { | |
opacity: 1; | |
transform: translateY(0) scale(1.2); | |
} | |
40% { | |
transform: translateY(-20px) translateX(10px) scale(1); | |
} | |
60% { | |
transform: translateY(-10px) translateX(-15px) scale(1.1); | |
} | |
80% { | |
transform: translateY(-30px) translateX(20px) scale(0.9); | |
} | |
100% { | |
opacity: 0; | |
transform: translateY(-50px) translateX(0) scale(0.5); | |
} | |
} | |
.animated-emoji.show { | |
animation: emojiPop 2s ease-out forwards; | |
} | |
.counter { | |
position: absolute; | |
top: 20px; | |
right: 20px; | |
background: rgba(255, 255, 255, 0.9); | |
padding: 8px 12px; | |
border-radius: 20px; | |
font-size: 15px; | |
font-weight: bold; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
user-select: none; | |
} | |
.personal-counter { | |
position: absolute; | |
top: 20px; | |
right: 220px; | |
background: rgba(255, 255, 255, 0.9); | |
padding: 8px 12px; | |
border-radius: 20px; | |
font-size: 15px; | |
font-weight: bold; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
user-select: none; | |
} | |
@media (prefers-color-scheme: dark) { | |
body { | |
background: #1a1a1a; | |
} | |
.button-3d { | |
background: #2d2d2d; | |
box-shadow: | |
0 10px 20px rgba(0, 0, 0, 0.4), | |
0 6px 10px rgba(0, 0, 0, 0.3), | |
inset 0 -3px 0 rgba(0, 0, 0, 0.2); | |
} | |
.button-3d:hover { | |
box-shadow: | |
0 12px 24px rgba(0, 0, 0, 0.4), | |
0 8px 12px rgba(0, 0, 0, 0.3), | |
inset 0 -3px 0 rgba(0, 0, 0, 0.2); | |
} | |
.button-3d:active { | |
box-shadow: | |
0 4px 8px rgba(0, 0, 0, 0.4), | |
0 2px 4px rgba(0, 0, 0, 0.3), | |
inset 0 -1px 0 rgba(0, 0, 0, 0.2); | |
} | |
.counter, .personal-counter { | |
background: rgba(45, 45, 45, 0.9); | |
color: white; | |
} | |
.unmute-notification { | |
background: rgba(45, 45, 45, 0.9); | |
color: white; | |
} | |
} | |
.unmute-notification { | |
position: fixed; | |
bottom: 20px; | |
left: 50%; | |
transform: translateX(-50%); | |
background: rgba(255, 255, 255, 0.9); | |
padding: 8px 16px; | |
border-radius: 16px; | |
font-size: 14px; | |
color: #333; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
user-select: none; | |
z-index: 1000; | |
white-space: nowrap; | |
max-width: 90vw; | |
text-align: center; | |
} | |
@media (max-width: 480px) { | |
.unmute-notification { | |
font-size: 12px; | |
padding: 6px 12px; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="personal-counter" id="personalCounter">My Clicks: 0</div> | |
<button class="button-3d" id="emojiButton"> | |
<span class="emoji">🦎</span> | |
</button> | |
<div class="unmute-notification">Unmute your phone if you don't hear sound 🔊</div> | |
<script> | |
const button = document.getElementById('emojiButton'); | |
const personalCounter = document.getElementById('personalCounter'); | |
let personalClickCount = 0; | |
const audioPool = []; | |
const poolSize = 5; | |
let currentAudioIndex = 0; | |
let audioBuffer = null; | |
let audioContext = null; | |
function initializeAudioContext() { | |
if (!audioContext) { | |
audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
} | |
return audioContext; | |
} | |
async function loadAudioBuffer() { | |
if (audioBuffer) return audioBuffer; | |
try { | |
const audioCtx = initializeAudioContext(); | |
const response = await fetch('lizard.wav'); | |
const arrayBuffer = await response.arrayBuffer(); | |
audioBuffer = await audioCtx.decodeAudioData(arrayBuffer); | |
return audioBuffer; | |
} catch (error) { | |
console.log('Failed to load audio buffer, falling back to HTML Audio:', error); | |
return null; | |
} | |
} | |
for (let i = 0; i < poolSize; i++) { | |
const audio = new Audio('lizard.wav'); | |
audio.preload = 'auto'; | |
audio.volume = 1.0; | |
audioPool.push(audio); | |
} | |
function loadPersonalClickCount() { | |
const saved = localStorage.getItem('personalClickCount'); | |
personalClickCount = saved ? parseInt(saved, 10) : 0; | |
updatePersonalCounterDisplay(); | |
} | |
function savePersonalClickCount() { | |
localStorage.setItem('personalClickCount', personalClickCount.toString()); | |
} | |
function updatePersonalCounterDisplay() { | |
const formatter = new Intl.NumberFormat('en-US'); | |
personalCounter.textContent = `My Clicks: ${formatter.format(personalClickCount)}`; | |
} | |
function createAnimatedEmoji() { | |
const emoji = document.createElement('div'); | |
emoji.className = 'animated-emoji'; | |
emoji.textContent = '🦎'; | |
const x = Math.random() * (window.innerWidth - 100); | |
const y = Math.random() * (window.innerHeight * 0.6) + (window.innerHeight * 0.2); | |
emoji.style.left = x + 'px'; | |
emoji.style.top = y + 'px'; | |
document.body.appendChild(emoji); | |
setTimeout(() => emoji.classList.add('show'), 10); | |
setTimeout(() => { | |
if (emoji.parentNode) { | |
document.body.removeChild(emoji); | |
} | |
}, 2000); | |
} | |
async function playSound() { | |
// Try Web Audio API first for better performance | |
if (audioBuffer && audioContext) { | |
try { | |
const audioCtx = audioContext; | |
if (audioCtx.state === 'suspended') { | |
await audioCtx.resume(); | |
} | |
const source = audioCtx.createBufferSource(); | |
source.buffer = audioBuffer; | |
source.connect(audioCtx.destination); | |
source.start(0); | |
createAnimatedEmoji(); | |
return; | |
} catch (error) { | |
console.log('Web Audio API failed, falling back to HTML Audio:', error); | |
} | |
} | |
const audio = audioPool[currentAudioIndex]; | |
if (!audio.paused) { | |
audio.pause(); | |
} | |
audio.currentTime = 0; | |
try { | |
await audio.play(); | |
} catch (error) { | |
currentAudioIndex = (currentAudioIndex + 1) % poolSize; | |
} | |
createAnimatedEmoji(); | |
currentAudioIndex = (currentAudioIndex + 1) % poolSize; | |
} | |
button.addEventListener('click', () => { | |
// Always play sound immediately - highest priority | |
playSound(); | |
// Update personal counter immediately | |
personalClickCount++; | |
updatePersonalCounterDisplay(); | |
savePersonalClickCount(); | |
}); | |
// Initialize audio system and preload files when page loads | |
window.addEventListener('load', async () => { | |
// Initialize Web Audio API and load buffer | |
try { | |
await loadAudioBuffer(); | |
} catch (error) { | |
console.log('Web Audio initialization failed, using HTML Audio fallback'); | |
} | |
// Preload HTML Audio fallback files | |
audioPool.forEach(audio => { | |
audio.load(); | |
}); | |
// Load personal click count from localStorage | |
loadPersonalClickCount(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment