Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Matrix Code Rain</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&display=swap'); | |
body { | |
font-family: 'Inconsolata', monospace; | |
overflow: hidden; | |
background-color: #000; | |
margin: 0; | |
padding: 0; | |
} | |
.matrix-column { | |
position: relative; | |
display: inline-block; | |
color: #20C20E; | |
text-shadow: 0 0 5px #20C20E; | |
width: 20px; | |
height: 100vh; | |
overflow: hidden; | |
} | |
.matrix-char { | |
position: absolute; | |
opacity: 0; | |
animation: | |
fadeIn 0.1s forwards, | |
fall linear forwards; | |
} | |
@keyframes fadeIn { | |
to { opacity: 1; } | |
} | |
@keyframes fall { | |
to { transform: translateY(100vh); } | |
} | |
.glitch { | |
position: relative; | |
} | |
.glitch::before, .glitch::after { | |
content: attr(data-text); | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: #000; | |
} | |
.glitch::before { | |
left: 2px; | |
text-shadow: -2px 0 #ff00c1; | |
clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); | |
animation: glitch-anim-1 2s infinite linear alternate-reverse; | |
} | |
.glitch::after { | |
left: -2px; | |
text-shadow: -2px 0 #00fff9; | |
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%); | |
animation: glitch-anim-2 2s infinite linear alternate-reverse; | |
} | |
@keyframes glitch-anim-1 { | |
0% { transform: translateX(0); } | |
20% { transform: translateX(-3px); } | |
40% { transform: translateX(3px); } | |
60% { transform: translateX(-3px); } | |
80% { transform: translateX(3px); } | |
100% { transform: translateX(0); } | |
} | |
@keyframes glitch-anim-2 { | |
0% { transform: translateX(0); } | |
20% { transform: translateX(3px); } | |
40% { transform: translateX(-3px); } | |
60% { transform: translateX(3px); } | |
80% { transform: translateX(-3px); } | |
100% { transform: translateX(0); } | |
} | |
.scanline { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient( | |
to bottom, | |
rgba(32, 194, 14, 0.1) 0%, | |
rgba(32, 194, 14, 0.1) 50%, | |
rgba(32, 194, 14, 0) 51% | |
); | |
background-size: 100% 8px; | |
animation: scanline 8s linear infinite; | |
pointer-events: none; | |
z-index: 100; | |
} | |
@keyframes scanline { | |
0% { transform: translateY(-100%); } | |
100% { transform: translateY(100%); } | |
} | |
.ripple { | |
position: absolute; | |
border-radius: 50%; | |
background-color: rgba(32, 194, 14, 0.7); | |
transform: scale(0); | |
opacity: 1; | |
pointer-events: none; | |
animation: ripple 1s linear; | |
} | |
@keyframes ripple { | |
to { | |
transform: scale(30); | |
opacity: 0; | |
} | |
} | |
</style> | |
</head> | |
<body class="bg-black text-green-500 h-screen w-screen flex flex-col"> | |
<!-- Header with glitch effect --> | |
<header class="p-4 border-b border-green-500/20 relative overflow-hidden"> | |
<h1 class="glitch text-3xl font-bold text-center" data-text="MATRIX CODE RAIN">MATRIX CODE RAIN</h1> | |
<div class="absolute top-0 left-0 w-full h-full bg-green-500/5 pointer-events-none"></div> | |
</header> | |
<!-- Main matrix display --> | |
<main class="flex-1 relative overflow-hidden"> | |
<div id="matrix-container" class="h-full w-full flex justify-center items-center"></div> | |
<div class="scanline"></div> | |
</main> | |
<!-- Footer with controls --> | |
<footer class="p-4 border-t border-green-500/20 flex justify-between items-center"> | |
<div class="flex space-x-4"> | |
<button id="speed-up" class="px-3 py-1 bg-green-900/50 border border-green-500 rounded hover:bg-green-800/70 transition"> | |
<span class="text-xs">SPEED +</span> | |
</button> | |
<button id="speed-down" class="px-3 py-1 bg-green-900/50 border border-green-500 rounded hover:bg-green-800/70 transition"> | |
<span class="text-xs">SPEED -</span> | |
</button> | |
<button id="density-up" class="px-3 py-1 bg-green-900/50 border border-green-500 rounded hover:bg-green-800/70 transition"> | |
<span class="text-xs">DENSITY +</span> | |
</button> | |
<button id="density-down" class="px-3 py-1 bg-green-900/50 border border-green-500 rounded hover:bg-green-800/70 transition"> | |
<span class="text-xs">DENSITY -</span> | |
</button> | |
</div> | |
<div class="text-xs opacity-70"> | |
<span id="fps-counter">FPS: 0</span> | |
</div> | |
<button id="toggle-matrix" class="px-3 py-1 bg-green-900/50 border border-green-500 rounded hover:bg-green-800/70 transition"> | |
<span class="text-xs">TOGGLE MATRIX</span> | |
</button> | |
</footer> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
// Configuration | |
const config = { | |
columns: 80, | |
minChars: 5, | |
maxChars: 25, | |
speed: 2, // Lower is faster | |
density: 0.8, | |
chars: "日ハミヒーウシナモニサワツオリアホテマケメエカキムユラセネスタヌヘヲイクコソチトノフヤヨルレロン0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", | |
running: true | |
}; | |
// State | |
let columns = []; | |
let lastFrameTime = 0; | |
let fps = 0; | |
let frameCount = 0; | |
let lastFpsUpdate = 0; | |
// DOM elements | |
const matrixContainer = document.getElementById('matrix-container'); | |
const fpsCounter = document.getElementById('fps-counter'); | |
// Initialize matrix | |
function initMatrix() { | |
matrixContainer.innerHTML = ''; | |
columns = []; | |
// Calculate column width based on container width | |
const columnWidth = Math.max(20, window.innerWidth / config.columns); | |
for (let i = 0; i < config.columns; i++) { | |
const column = document.createElement('div'); | |
column.className = 'matrix-column'; | |
column.style.width = `${columnWidth}px`; | |
column.style.height = '100vh'; | |
// Random delay for each column | |
column.dataset.delay = Math.random() * 2000; | |
column.dataset.lastUpdate = 0; | |
column.dataset.speed = config.speed + Math.random() * 2 - 1; | |
matrixContainer.appendChild(column); | |
columns.push(column); | |
// Initial characters | |
const initialChars = Math.floor(Math.random() * (config.maxChars - config.minChars) + config.minChars); | |
for (let j = 0; j < initialChars; j++) { | |
addCharToColumn(column, -j * 20); | |
} | |
} | |
} | |
// Add a character to a column at specific position | |
function addCharToColumn(column, yPos) { | |
const char = document.createElement('div'); | |
char.className = 'matrix-char'; | |
char.textContent = getRandomChar(); | |
// Random brightness | |
const brightness = Math.random(); | |
if (brightness > 0.8) { | |
char.style.color = '#FFFFFF'; | |
char.style.textShadow = '0 0 8px #FFFFFF'; | |
} else if (brightness > 0.5) { | |
char.style.color = '#20C20E'; | |
char.style.textShadow = '0 0 5px #20C20E'; | |
} else { | |
char.style.color = '#0A5C07'; | |
char.style.textShadow = 'none'; | |
} | |
// Set random animation duration between 2-5 seconds | |
const duration = 2 + Math.random() * 3; | |
char.style.animationDuration = `${duration}s`; | |
// Set initial position | |
char.style.left = '0'; | |
char.style.top = `${yPos}px`; | |
column.appendChild(char); | |
// Remove character after animation completes | |
setTimeout(() => { | |
char.remove(); | |
}, duration * 1000); | |
} | |
// Generate random matrix character | |
function getRandomChar() { | |
return config.chars.charAt(Math.floor(Math.random() * config.chars.length)); | |
} | |
// Update a single column | |
function updateColumn(column, now) { | |
const lastUpdate = parseFloat(column.dataset.lastUpdate); | |
const speed = parseFloat(column.dataset.speed); | |
if (now - lastUpdate < speed * 100) return; | |
// Skip some updates based on density | |
if (Math.random() > config.density) return; | |
column.dataset.lastUpdate = now; | |
// Add new character at top | |
addCharToColumn(column, -20); | |
// Randomly reset the column | |
if (Math.random() < 0.005) { | |
const chars = column.querySelectorAll('.matrix-char'); | |
chars.forEach(char => { | |
char.style.opacity = '0'; | |
char.style.transition = 'opacity 0.5s ease'; | |
}); | |
} | |
} | |
// Main animation loop | |
function animate(now) { | |
if (!lastFrameTime) lastFrameTime = now; | |
const deltaTime = now - lastFrameTime; | |
lastFrameTime = now; | |
frameCount++; | |
if (now - lastFpsUpdate >= 1000) { | |
fps = Math.round((frameCount * 1000) / (now - lastFpsUpdate)); | |
fpsCounter.textContent = `FPS: ${fps}`; | |
lastFpsUpdate = now; | |
frameCount = 0; | |
} | |
if (config.running) { | |
columns.forEach(column => updateColumn(column, now)); | |
} | |
requestAnimationFrame(animate); | |
} | |
// Event listeners for controls | |
document.getElementById('speed-up').addEventListener('click', () => { | |
config.speed = Math.max(0.5, config.speed - 0.5); | |
}); | |
document.getElementById('speed-down').addEventListener('click', () => { | |
config.speed = Math.min(5, config.speed + 0.5); | |
}); | |
document.getElementById('density-up').addEventListener('click', () => { | |
config.density = Math.min(1, config.density + 0.1); | |
}); | |
document.getElementById('density-down').addEventListener('click', () => { | |
config.density = Math.max(0.1, config.density - 0.1); | |
}); | |
document.getElementById('toggle-matrix').addEventListener('click', () => { | |
config.running = !config.running; | |
document.getElementById('toggle-matrix').querySelector('span').textContent = | |
config.running ? 'TOGGLE MATRIX' : 'RESUME MATRIX'; | |
}); | |
// Handle window resize | |
window.addEventListener('resize', () => { | |
initMatrix(); | |
}); | |
// Start everything | |
initMatrix(); | |
requestAnimationFrame(animate); | |
// Easter egg - click anywhere to create a ripple effect | |
document.addEventListener('click', (e) => { | |
const ripple = document.createElement('div'); | |
ripple.className = 'ripple'; | |
ripple.style.left = `${e.clientX - 10}px`; | |
ripple.style.top = `${e.clientY - 10}px`; | |
ripple.style.width = '20px'; | |
ripple.style.height = '20px'; | |
document.body.appendChild(ripple); | |
setTimeout(() => { | |
ripple.remove(); | |
}, 1000); | |
}); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=MarkTheArtist/matrix-code-rain" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |