matrix-code-rain / index.html
MarkTheArtist's picture
Add 2 files
8644757 verified
<!DOCTYPE html>
<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>