Bitte warten

JavaScript: MatrixRain

Hier wird die Intro-Animation der Matrix-Filme nachgebildet (Font: Matrix-Code).

Und das ist der dazugehörige Quelltext:

Code kopieren
<!DOCTYPE html>
<html lang='en'>
  <head>
    <title>MatrixRain</title>
    <meta charset='UTF-8'>
    <style>
      @font-face { font-family:'Matrix-Code'; font-weight:normal; font-style:normal; src:url(Matrix-Code.ttf); }
      body { background:hsl(0,0%,25%); }
      button { width:70px; }
      #matrixbox { margin:20px auto 0; text-align:center; }
      #matrix { background:hsl(100,40%,5%); margin:auto auto 10px; position:relative; border-radius:10px; }
    </style>
  </head>
  <body>
    <div id='matrixbox'>
      <canvas id='matrix'></canvas>
      <div>
        <button id='matrixButton1' class='bigbutton' onclick='matrixPlayPause();'>Play</button>
        <button id='matrixButton2' class='bigbutton' onclick='matrixInit();'>Reset</button>
      </div>
    </div>
    <script>
      function matrixChar() {
        cid = +(Math.random() > .8);
        return chars[cid][Math.floor(Math.random() * chars[cid].length)];
      }
      
      function matrixInit() {
        matrix = document.getElementById('matrix');
        fs = 15;
        cols = 50;
        rows = 40;
        chars = [
          "アウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤヨラリワ012345789",
          "ー╌▪*+|z:©¦\"<>\uE937"
        ];
        matrixPos = Array.from(
          { length: cols }, () => Array.from(
            { length: rows }, () => matrixChar()
          )
        );
        matrixColors = Array.from(
          { length: cols }, () => Array.from(
            { length: rows }, () => 0
          )
        );
        blankColors = structuredClone(matrixColors);
        fx = fs * 1.1;
        fy = fs * 0.9;
        matrix.width  = cols * fx;
        matrix.height = rows * fy + fs * .2;
        drops = [];
        cx = matrix.getContext('2d');
        cx.font = fs + 'px Matrix-Code';
        if (  // shadowBlur performs badly in Firefox
          !navigator.userAgent.includes('Firefox') &&
          !navigator.userAgent.includes('FxiOS')
        ) {
          cx.shadowBlur = fs * .5;
          doShadow = true;
        } else doShadow = false;
        doMatrix = false;
        matrixPlayPause();
        if (typeof animationFrameId !== 'undefined') cancelAnimationFrame(animationFrameId);
        animationFrameId = requestAnimationFrame(matrixRain);
      }
      
      function matrixRain() {
        matrixNow = Date.now();
        if (doMatrix) {
          // create new drop
          if (Math.random() < .6) drops.push([
            Math.floor(Math.random() * cols),           // 0 column
            0,                                          // 1 row
            Math.floor(Math.random() * rows * .7 + 5),  // 2 length
            100 * (1 - Math.random() * .7),             // 3 friction
            matrixNow                                   // 4 last timestamp
          ]);
          // update colors
          matrixColors = structuredClone(blankColors);
          newdrops = [];
          for (d = 0; d < drops.length; d++) {
            for (l = 0; l < drops[d][2]; l++) {
              y = drops[d][1] - drops[d][2] + l;
              newColor = (l < 4 ?
                (l + 1) * .18 :
                (l == drops[d][2] - 1 ? 1 : .9)
              );
              if (
                y >= 0 && y < rows &&
                matrixColors[drops[d][0]][y] < newColor
              ) matrixColors[drops[d][0]][y] = newColor;
            }
            if (matrixNow - drops[d][4] > drops[d][3]) {
              drops[d][1]++;
              drops[d][4] = matrixNow;
            }
            if (drops[d][1] < rows + drops[d][2]) newdrops.push(drops[d]);
          }
          drops = newdrops;
          // let it rain
          cx.clearRect(0, 0, matrix.width, matrix.height);
          for (x = 0; x < cols; x++) {
            for (y = 0; y < rows; y++) {
              cx.fillStyle = "hsla(100,40%," + (5 + matrixColors[x][y] * (matrixColors[x][y] == 1 ? 90 : 50)) + "%," + matrixColors[x][y] + ")";
              if (doShadow) cx.shadowColor = "hsl(100,40%," + (5 + matrixColors[x][y] * 60) + "%)";
              cx.fillText(matrixPos[x][y], (x + .07) * fx,fs + y * fy);
              if (Math.random() < .02) matrixPos[x][y] = matrixChar();
            }
          }
        }
        animationFrameId = requestAnimationFrame(matrixRain);
      }
      
      function matrixPlayPause() {
        document.getElementById('matrixButton1').innerHTML = (doMatrix ? "Play" : "Pause");
        doMatrix = !doMatrix;
        if (!doMatrix) {
          animationFrameId = null;
          cancelAnimationFrame(animationFrameId);
        }
      }
      matrixInit();
    </script>
  </body>
</html>