diff options
Diffstat (limited to 'head.html')
| -rw-r--r-- | head.html | 97 |
1 files changed, 97 insertions, 0 deletions
@@ -32,3 +32,100 @@ document.addEventListener('DOMContentLoaded', function() { } }); </script> +<script> +(function() { + if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; + + var CHARS = 'ヲイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~0123456789'; + var FONT_SIZE = 14; + var TRAIL_LEN = 12; + var TRAIL_FADE = 0.09; + var GREEN_MAX = 0.55; + var PURPLE_MAX = 0.75; + var PURPLE_PROB = 0.35; + var SPEED_MIN = 0.3; + var SPEED_MAX = 0.8; + var CANVAS_W_RATIO = 0.65; + var BG_CLEAR = 'rgba(12,21,32,0.18)'; + + function randChar() { + return CHARS[Math.floor(Math.random() * CHARS.length)]; + } + + function makeColumn() { + return { + y: Math.random() * -20, + speed: SPEED_MIN + Math.random() * (SPEED_MAX - SPEED_MIN), + purple: Math.random() < PURPLE_PROB, + chars: Array.from({length: TRAIL_LEN}, randChar) + }; + } + + function init(canvas, header) { + canvas.width = Math.floor(header.offsetWidth * CANVAS_W_RATIO); + canvas.height = header.offsetHeight; + var cols = Math.floor(canvas.width / FONT_SIZE); + return Array.from({length: cols}, makeColumn); + } + + function draw(ctx, canvas, drops) { + ctx.fillStyle = BG_CLEAR; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.font = FONT_SIZE + 'px "JetBrains Mono", monospace'; + + var rows = Math.ceil(canvas.height / FONT_SIZE); + drops.forEach(function(drop, i) { + var x = i * FONT_SIZE; + for (var r = 0; r < TRAIL_LEN; r++) { + var row = Math.floor(drop.y) - r; + if (row < 0 || row >= rows) continue; + var fade = Math.max(0, 1 - r * TRAIL_FADE); + if (r === 0 && drop.purple) { + ctx.fillStyle = 'rgba(168,85,247,' + (PURPLE_MAX * fade).toFixed(2) + ')'; + } else { + ctx.fillStyle = 'rgba(0,255,136,' + (GREEN_MAX * fade).toFixed(2) + ')'; + } + if (Math.random() < 0.03) drop.chars[r % TRAIL_LEN] = randChar(); + ctx.fillText(drop.chars[r % TRAIL_LEN], x, row * FONT_SIZE); + } + drop.y += drop.speed; + if (drop.y * FONT_SIZE > canvas.height + 200) { + drop.y = Math.random() * -10; + drop.speed = SPEED_MIN + Math.random() * (SPEED_MAX - SPEED_MIN); + drop.purple = Math.random() < PURPLE_PROB; + } + }); + } + + document.addEventListener('DOMContentLoaded', function() { + var header = document.querySelector('table#header'); + if (!header) return; + + var canvas = document.createElement('canvas'); + canvas.id = 'matrix-rain-canvas'; + canvas.style.cssText = 'position:absolute;top:0;right:0;height:100%;pointer-events:none;z-index:0;'; + header.appendChild(canvas); + + var fade = document.createElement('div'); + fade.id = 'matrix-rain-fade'; + fade.style.cssText = 'position:absolute;top:0;left:0;bottom:0;width:75%;background:linear-gradient(to right,rgba(12,21,32,0.88) 40%,transparent 100%);pointer-events:none;z-index:1;'; + header.appendChild(fade); + + var ctx = canvas.getContext('2d'); + var drops = init(canvas, header); + + var raf; + function loop() { + draw(ctx, canvas, drops); + raf = requestAnimationFrame(loop); + } + loop(); + + window.addEventListener('resize', function() { + cancelAnimationFrame(raf); + drops = init(canvas, header); + loop(); + }); + }); +})(); +</script> |
