Cyberpunk & Visual Toys

MATRIX DIGITAL RAIN

100% browser-rendered Cyberpunk digital code rain visualizer. Customize character sets (Katakana, Binary, ASCII, Hex), rain speed, font size, and color palettes.

Font Size 16px
Fall Speed 1x
Developer Reference

Core Algorithm & Standalone Script

Standalone, zero-dependency JavaScript implementation powering this tool. Free to inspect, copy, and build upon.

const canvas = document.getElementById('matrix-canvas');
    const ctx = canvas.getContext('2d');
    const wrap = document.getElementById('canvas-wrap');

    const themeSelect = document.getElementById('select-theme');
    const charSelect = document.getElementById('select-charset');
    const fontInput = document.getElementById('input-font');
    const speedInput = document.getElementById('input-speed');

    const CHARSETS = {
      katakana: 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン0123456789',
      binary: '01',
      hex: '0123456789ABCDEF',
      ascii: '@#$%&*+-/<>~^'
    };

    const THEMES = {
      matrix: '#00ff66',
      red: '#ff2200',
      cyan: '#00e5ff',
      amber: '#ffaa00',
      purple: '#b537f2'
    };

    let fontSize = 16;
    let columns = 0;
    let drops = [];
    let animId = null;

    function resizeCanvas() {
      canvas.width = wrap.clientWidth;
      canvas.height = wrap.clientHeight;
      fontSize = parseInt(fontInput.value);
      columns = Math.floor(canvas.width / fontSize);
      drops = [];
      for (let i = 0; i < columns; i++) {
        drops[i] = Math.floor(Math.random() * -100);
      }
    }

    function drawMatrix() {
      ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      const color = THEMES[themeSelect.value] || '#00ff66';
      ctx.fillStyle = color;
      ctx.font = fontSize + 'px monospace';

      const charset = CHARSETS[charSelect.value] || CHARSETS.katakana;
      const speed = parseInt(speedInput.value);

      for (let i = 0; i < drops.length; i++) {
        const text = charset[Math.floor(Math.random() * charset.length)];
        const x = i * fontSize;
        const y = drops[i] * fontSize;

        ctx.fillText(text, x, y);

        if (y > canvas.height && Math.random() > 0.975) {
          drops[i] = 0;
        }
        drops[i] += speed * 0.8;
      }

      animId = requestAnimationFrame(drawMatrix);
    }

    fontInput.addEventListener('input', () => {
      document.getElementById('val-font').textContent = fontInput.value + 'px';
      resizeCanvas();
    });

    speedInput.addEventListener('input', () => {
      document.getElementById('val-speed').textContent = speedInput.value + 'x';
    });

    themeSelect.addEventListener('change', () => {});
    charSelect.addEventListener('change', () => {});

    document.getElementById('btn-fullscreen').addEventListener('click', () => {
      if (!document.fullscreenElement) {
        wrap.requestFullscreen();
      } else {
        document.exitFullscreen();
      }
    });

    document.getElementById('btn-screenshot').addEventListener('click', () => {
      const a = document.createElement('a');
      a.href = canvas.toDataURL('image/png');
      a.download = 'matrix-rain.png';
      a.click();
    });

    window.addEventListener('resize', resizeCanvas);

    resizeCanvas();
    drawMatrix();