<!DOCTYPE html>
<html>
<head>
<title>1. Crimson Glitch Stream</title>
<style>
body {
margin: 0;
background-color: var(--matrix-bg);
overflow: hidden;
}
canvas {
display: block;
}
:root {
--matrix-bg: #050000;
--matrix-text: #b81c1c;
--matrix-trail: rgba(10, 0, 0, 0.05);
--matrix-flash: #ffeaea;
--matrix-shadow: #ff4d4d;
/* Default to monospace if no global font is set */
font-family: var(--htmlhub-font, monospace);
}
</style>
</head>
<body>
<canvas id="matrixCanvas"></canvas>
<script>
const canvas = document.getElementById('matrixCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Characters used in the stream, focusing on hex and symbols
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()[]{};:?<>~';
const hexChars = '0123456789ABCDEF';
const characterSet = (hexChars + chars).split('');
const fontSize = 16;
const columns = Math.floor(canvas.width / fontSize);
// Array to store the Y position of each stream column
const drops = Array(columns).fill(1);
function draw() {
// Create the fading trail effect by drawing a semi-transparent background
// Fetch color from CSS variable for live customization
const style = getComputedStyle(document.documentElement);
ctx.fillStyle = style.getPropertyValue('--matrix-trail').trim() || 'rgba(10, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Main text color
ctx.fillStyle = style.getPropertyValue('--matrix-text').trim() || '#b81c1c';
// Use global font variable
const fontStack = style.getPropertyValue('--htmlhub-font').trim() || 'monospace';
ctx.font = `${fontSize}px ${fontStack}`;
for (let i = 0; i < drops.length; i++) {
const text = characterSet[Math.floor(Math.random() * characterSet.length)];
const x = i * fontSize;
// Snap Y to grid to prevent jitter at slow speeds
const y = Math.floor(drops[i]) * fontSize;
// Main draw call for the character
ctx.fillText(text, x, y);
// Add the "glitch" effect randomly
if (Math.random() > 0.985) {
// Flash effect: Draw a brighter, slightly offset character
ctx.fillStyle = style.getPropertyValue('--matrix-flash').trim() || '#ffeaea';
ctx.shadowColor = style.getPropertyValue('--matrix-shadow').trim() || '#ff4d4d';
ctx.shadowBlur = 10;
ctx.fillText(text, x + (Math.random() * 4 - 2), y);
// Reset styles
ctx.fillStyle = style.getPropertyValue('--matrix-text').trim() || '#b81c1c';
ctx.shadowBlur = 0;
}
// Reset a stream when it reaches the bottom of the screen
// Add randomness to make the streams less uniform
if (y > canvas.height && Math.random() > 0.975) {
drops[i] = 0;
}
// Increment by speed factor
const speed = parseFloat(style.getPropertyValue('--htmlhub-speed')) || 1.0;
drops[i] += speed;
}
}
// Set animation to loop. The internal logic handles the seamlessness.
setInterval(draw, 33);
// Resize canvas if window size changes
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Re-initialize columns and drops array on resize
const newColumns = Math.floor(canvas.width / fontSize);
drops.length = 0; // Clear the array
for (let i = 0; i < newColumns; i++) {
drops.push(1);
}
});
</script>
</body>
</html>
<canvas id="matrixCanvas"></canvas>
body {
margin: 0;
background-color: var(--matrix-bg);
overflow: hidden;
}
canvas {
display: block;
}
:root {
--matrix-bg: #050000;
--matrix-text: #b81c1c;
--matrix-trail: rgba(10, 0, 0, 0.05);
--matrix-flash: #ffeaea;
--matrix-shadow: #ff4d4d;
/* Default to monospace if no global font is set */
font-family: var(--htmlhub-font, monospace);
}
const canvas = document.getElementById('matrixCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Characters used in the stream, focusing on hex and symbols
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()[]{};:?<>~';
const hexChars = '0123456789ABCDEF';
const characterSet = (hexChars + chars).split('');
const fontSize = 16;
const columns = Math.floor(canvas.width / fontSize);
// Array to store the Y position of each stream column
const drops = Array(columns).fill(1);
function draw() {
// Create the fading trail effect by drawing a semi-transparent background
// Fetch color from CSS variable for live customization
const style = getComputedStyle(document.documentElement);
ctx.fillStyle = style.getPropertyValue('--matrix-trail').trim() || 'rgba(10, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Main text color
ctx.fillStyle = style.getPropertyValue('--matrix-text').trim() || '#b81c1c';
// Use global font variable
const fontStack = style.getPropertyValue('--htmlhub-font').trim() || 'monospace';
ctx.font = `${fontSize}px ${fontStack}`;
for (let i = 0; i < drops.length; i++) {
const text = characterSet[Math.floor(Math.random() * characterSet.length)];
const x = i * fontSize;
// Snap Y to grid to prevent jitter at slow speeds
const y = Math.floor(drops[i]) * fontSize;
// Main draw call for the character
ctx.fillText(text, x, y);
// Add the "glitch" effect randomly
if (Math.random() > 0.985) {
// Flash effect: Draw a brighter, slightly offset character
ctx.fillStyle = style.getPropertyValue('--matrix-flash').trim() || '#ffeaea';
ctx.shadowColor = style.getPropertyValue('--matrix-shadow').trim() || '#ff4d4d';
ctx.shadowBlur = 10;
ctx.fillText(text, x + (Math.random() * 4 - 2), y);
// Reset styles
ctx.fillStyle = style.getPropertyValue('--matrix-text').trim() || '#b81c1c';
ctx.shadowBlur = 0;
}
// Reset a stream when it reaches the bottom of the screen
// Add randomness to make the streams less uniform
if (y > canvas.height && Math.random() > 0.975) {
drops[i] = 0;
}
// Increment by speed factor
const speed = parseFloat(style.getPropertyValue('--htmlhub-speed')) || 1.0;
drops[i] += speed;
}
}
// Set animation to loop. The internal logic handles the seamlessness.
setInterval(draw, 33);
// Resize canvas if window size changes
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Re-initialize columns and drops array on resize
const newColumns = Math.floor(canvas.width / fontSize);
drops.length = 0; // Clear the array
for (let i = 0; i < newColumns; i++) {
drops.push(1);
}
});