(function () { var c = document.getElementById('hdr'); var ctx = c.getContext('2d'); var W, H, mouse = { x: -999, y: -999 }; var glitchX = 0, glitchY = 0; var glitchXTarget = 0, glitchYTarget = 0; var COLS = ['#00ffff', '#ff00ff', '#ffffff']; /*const ARTS = [ { lines: [ '' ] }, ]*/ var validARTS = ARTS.filter(function(a) { return a.lines.length > 0; }); var ART = validARTS[Math.floor(Math.random() * validARTS.length)].lines; var fontSize, LINE_H, ART_TOP, PAD_BOTTOM; function resize() { W = c.width = c.offsetWidth; var maxChars = ART.reduce(function(max, l) { return Math.max(max, l.length); }, 0); fontSize = Math.min(16, (W * 0.95) / maxChars * 1.6); LINE_H = fontSize * 1; ART_TOP = LINE_H * 2; PAD_BOTTOM = LINE_H * 2; H = c.height = Math.ceil(ART_TOP + ART.length * LINE_H + PAD_BOTTOM); buildScanlines(); } var scanlines = document.createElement('canvas'); function buildScanlines() { var headerH = ART_TOP + ART.length * LINE_H + PAD_BOTTOM; scanlines.width = 1; scanlines.height = headerH; var sctx = scanlines.getContext('2d'); sctx.clearRect(0, 0, 1, headerH); for (var sy = 0; sy < headerH; sy += 3) { sctx.fillStyle = '#101010'; sctx.fillRect(0, sy, 1, 1); } } window.addEventListener('resize', function () { resize(); }); window.addEventListener('DOMContentLoaded', function() { resize(); requestAnimationFrame(loop); }); var moveTimer; var glitchTarget = 0; var lastX = 0, lastY = 0; document.addEventListener('mousemove', function (e) { var nx = e.clientX; var ny = e.clientY; var dx = nx - lastX; var dy = ny - lastY; mouse.x = nx; mouse.y = ny; lastX = nx; lastY = ny; glitchXTarget = Math.min(1, Math.abs(dx) / 16); glitchYTarget = Math.min(1, Math.abs(dy) / 16); clearTimeout(moveTimer); moveTimer = setTimeout(function () { glitchXTarget = 0; glitchYTarget = 0; }, 100); }); document.addEventListener('mouseleave', function () { mouse.x = -999; glitchXTarget = 0; glitchYTarget = 0; }); document.addEventListener('touchmove', function (e) { var touch = e.touches[0]; var nx = touch.clientX; var ny = touch.clientY; var dx = nx - lastX; var dy = ny - lastY; mouse.x = nx; mouse.y = ny; lastX = nx; lastY = ny; glitchXTarget = Math.min(1, Math.abs(dx) / 16); glitchYTarget = Math.min(1, Math.abs(dy) / 16); clearTimeout(moveTimer); moveTimer = setTimeout(function () { glitchXTarget = 0; glitchYTarget = 0; }, 100); }, { passive: true }); document.addEventListener('touchend', function () { glitchXTarget = 0; glitchYTarget = 0; }); /* ── text ── */ function drawText(ox, oy, col, alpha) { ctx.save(); ctx.globalAlpha = alpha; ctx.fillStyle = col; ctx.font = fontSize + 'px deltarune'; ctx.textAlign = 'center'; ctx.textBaseline = 'top'; for (var i = 0; i < ART.length; i++) { ctx.fillText(ART[i], W / 2 + ox, ART_TOP + i * LINE_H + oy, W * 0.95); } ctx.restore(); } /* ── proximity glow on letters ── */ function drawGlow() { var cx = W / 2; var cy = ART_TOP + (ART.length * LINE_H) / 2; var dx = mouse.x - cx; var dy = mouse.y - cy; var dist = Math.sqrt(dx * dx + dy * dy); var r = Math.max(0, 1 - dist / 220); var idle = (1 - r) * (Math.sin(t * 0.008) * 0.5 + 0.5) * 0.25; if (idle > 0) { ctx.save(); ctx.globalAlpha = idle * 0.15; ctx.fillStyle = '#00ffff'; ctx.font = fontSize + 'px deltarune'; ctx.textAlign = 'center'; ctx.textBaseline = 'top'; for (var d = 3; d <= 9; d += 3) { for (var i = 0; i < ART.length; i++) { ctx.fillText(ART[i], W / 2 + d, ART_TOP + i * LINE_H, W * 0.95); ctx.fillText(ART[i], W / 2 - d, ART_TOP + i * LINE_H, W * 0.95); ctx.fillText(ART[i], W / 2, ART_TOP + i * LINE_H + d, W * 0.95); ctx.fillText(ART[i], W / 2, ART_TOP + i * LINE_H - d, W * 0.95); } } ctx.restore(); } if (r <= 0) return; ctx.save(); ctx.globalAlpha = r * 0.3; ctx.fillStyle = '#ff00ff'; ctx.font = fontSize + 'px deltarune'; ctx.textAlign = 'center'; ctx.textBaseline = 'top'; for (var d = 3; d <= 9; d += 3) { for (var i = 0; i < ART.length; i++) { ctx.fillText(ART[i], W / 2 + d, ART_TOP + i * LINE_H, W * 0.95); ctx.fillText(ART[i], W / 2 - d, ART_TOP + i * LINE_H, W * 0.95); } } ctx.restore(); } /* ── main loop ── */ var t = 0, lastFrame = 0; function loop(ts) { requestAnimationFrame(loop); if (ts - lastFrame < 42) return; lastFrame = ts; t++; ctx.clearRect(0, 0, W, H); var headerH = ART_TOP + ART.length * LINE_H + PAD_BOTTOM; var splitX = glitchX * 16; var splitY = glitchY * 16; drawText(-splitX, -splitY, '#00ffff', 0.7); drawText( splitX, splitY, '#ff00ff', 0.7); drawText(0, 0, '#ffffff', 0.9); drawGlow(); /* scanline overlay */ var headerH = ART_TOP + ART.length * LINE_H + PAD_BOTTOM; ctx.drawImage(scanlines, 0, 0, W, headerH); glitchX += (glitchXTarget - glitchX) * 0.04; glitchY += (glitchYTarget - glitchY) * 0.04; } window.rerollArt = function() { ART = validARTS[Math.floor(Math.random() * validARTS.length)].lines; resize(); }; })();