<body>
<div id="origin"></div>
<form id="mtxform" name="mtxform">
<div>
<button id="play" type="button" onclick="mtx.show();">Play Your Own</button>
<br/>
<span id="inputext" class="hidden">
<textarea rows="100" cols="100" id="text" name="text">
          "The Computer Programmer Is 
      A Creator Of Universes For Which 
          (S)He Alone Is The Lawgiver. 
                    No Playwright, 
                  No Stage Director, 
                     No Emperor  
                - However Powerful - 
      Has Ever Exercised Such Absolute 
        Authority To Arrange A Stage, 
    Or Field Of Battle, And To Command 
Such Unswervingly Dutiful Actors Or Troops."
                           -Joseph Weizenbaum
  
</textarea>
<br/>
<button type="button" class='playMine' onclick="mtx.changeText();">Play</button>
</span>
</div>

</body>
@import url(https://fonts.googleapis.com/css?family=Cinzel:700);

html {
    overflow: hidden;
  }

  body {
    background:rgba(236, 240, 241,1.0);
    font-family: 'Cinzel', serif;
    width: 100%;
    height: 100%;
    user-select:none;
    -webkit-user-select:none;
    -moz-user-select:none;
  }
  #origin {
    position: absolute;
    height: 100vh;
    width: 100vw;
    left:12vw;
    font-size: 2.5vw;
    font-family: 'Cinzel', serif;
    overflow: hidden;
    border: none;
    color: #FFF;
    letter-spacing:3px;
    text-shadow:1px 1px hsla(0,0%,0%,0.4),
    2px 1px hsla(0,0%,0%,0.3),
    3px 1px hsla(0,0%,0%,0.2);
  }
  #origin span {
    position: relative;
    z-index: 1;
  }
  #mtxform {
    position: relative;
    z-index: 10;
        color:#000;
  }
  .hidden {
    visibility: hidden;
  }
  #play{
    width:10em;
    height:3em;
    border:none;
    background:#fff;
    font-size:1.5em;
    font-weight:boldl
    box-shadow:1px 1px 1px 1px  hsla(0,0%,0%,0.2);
  -webkit-box-shadow:1px 1px 1px 1px hsla(0,0%,0%,0.2);
  outline:none;
  }
  .playMine{
    display:inline-block;
    width:13vw;
    height:auto;
    border:none;
     padding:.5em;
    background:#fff;
    font-size:1.5em;
    font-weight:bold;
    box-shadow:1px 1px 1px 1px  hsla(0,0%,0%,0.05);
  -webkit-box-shadow:1px 1px 1px 1px  hsla(0,0%,0%,0.05);
  outline:none;
  }
  textarea{
  background:rgba(149, 165, 166,.5);
  border:none;
  color:rgba(52, 73, 94,1.0);
  box-shadow:1px 1px 1px 1px hsla(0,0%,0%,0.05);
  -webkit-box-shadow:1px 1px 1px 1px hsla(0,0%,0%,0.05);
  height:20vh;
  width:15vw;
  outline:none;
  cursor:grab;
  }
::-webkit-scrollbar {
    width: 12px;
   
}
 
::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 
    border-radius: 2px;
}
 
::-webkit-scrollbar-thumb {
    border-radius: 2px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
}
/*original author: Gerard Ferrandez - [Ge1doot] 
 http://www.dhteumeuleu.com 
           
 I manipulated the script a little bit to allow the option of playing your own text snippet && have the colors of the letters change to red when being reused from the previous line to form the new line, and lime when dropped from previous line.
*/
var mtx = function () {
  /* ==== private variables & methods ==== */
  var stop = false;
  var origin, lineDelay, charDelay;
  var colorText, colorMatch, colorGhost, elapsedTime;
  var lineIndex = 0;
  var lineChar  = [];
  var animStack = [];
  var colorStack = [];
  /* ==== rgb color ==== */
  function colorRGB (c) {
    return 'rgb('
      +Math.round(Math.min(225, Math.max(0, c[0])))+','
      +Math.round(Math.min(255, Math.max(0, c[1])))+','
      +Math.round(Math.min(120, Math.max(0, c[2])))+')';
  }
  /* ==== Easing functions ==== */
  function Ease () {}
  Ease.prototype = {
    ease : function () {
      this.m += this.s;
      this.x0 += (this.d * this.m * .0025);
      if (this.m == 20) this.s = -1;
      return this.x0;
    },
    init : function (x0, x1) {
      this.m = 0;
      this.s = 1;
      this.d = x1 - x0;
      this.x0 = x0;
    }
  }

  /* ==== Load Lines ==== */
  function loadLines () {
    // read text from HTML form
    text = document.forms.mtxform.text.value.split("\n");
    // loop through all lines
    for (var j = 0; j < text.length; j++) {
      var t = text[j];
      if (t) {
        var n = t.length;
        lineChar[j] = [];
        // first pass: create characters capture RELATIVE offset coordinates
        for (var i = 0; i < n; i++)
          lineChar[j][i] = new Character(t.charAt(i), j);
        // second pass: convert to absolute position
        for (var i = 0, o; o = lineChar[j][i]; i++) {
          if (o.c == "|") {
            // remove spaces
            lineChar[j].splice(i, 1);
            origin.removeChild(o.o);
            i--;
          } else {
            // convert to absolute position and render
            o.o.style.position = "absolute";
            o.moveHTML();
            // push first line in animation stack
            if (j == 0) pushAnim (o, charDelay * i);
          }
        }
      }
    }
  }
  /* ==== Character Constructor ==== */
  function Character (c, line) {
    if (c == " ") c = "|";
    this.c = c;
    // create HTML element and append the the container
    this.o = document.createElement("span");
    this.o.innerHTML = c;
    this.o.style.zIndex = 2;
    origin.appendChild(this.o);
    // capture relative offset positions !
    this.x0 = this.o.offsetLeft;
    this.y0 = -this.o.offsetHeight * 1.5;
    this.x1 = this.x0;
    this.x2 = this.x0;
    this.y1 = (line + 1) * this.o.offsetHeight;
    this.y2 = origin.offsetHeight;
    this.mx = new Ease();
    this.my = new Ease();
    this.c0 = [colorText[0], colorText[1], colorText[2]];
  }
  /* ==== Character functions ==== */
  Character.prototype = {
    // ---- character animation ----
    anim : function (i) {
      // temporization
      if (this.delay > 0) {
        if (elapsedTime)
          this.delay -= new Date().getTime() - elapsedTime;
      } else {
        // moving
        this.x0 = this.mx.ease();
        this.y0 = this.my.ease();
        this.moveHTML();
        if (!this.my.m && !this.mx.m) {
          // remove from stack
          animStack.splice(i, 1);
          // remove dead characters
          if (this.off) origin.removeChild(this.o);
        }
      }
    },
    // ----- color fading ------
    color : function (i) {
      this.c0[0] += this.cr[0];
      this.c0[1] += this.cr[1];
      this.c0[2] += this.cr[2];
      this.ci++;
      this.o.style.color = colorRGB(this.c0);
      if (this.ci >= this.cs)
        colorStack.splice(i, 1);
    },
    // ----- HTML positioning -----
    moveHTML : function () {
      this.o.style.left = Math.round(this.x0) + "px";
      this.o.style.top  = Math.round(this.y0) + "px";
    },
    // ----- init color fading ------
    colorFade : function (c1, steps) {
      this.cs = steps;
      this.cr = [(c1[0] - this.c0[0]) / steps, (c1[1] - this.c0[1]) / steps, (c1[2] - this.c0[2]) / steps];
      if (this.cr[0] != 0 || this.cr[1] != 0 || this.cr[2] != 0){
        this.ci = 0;
        colorStack.push (this);
      }
    }
  }
  /* ==== push character in the animation stack ==== */
  function pushAnim (o, delay) {
    // init ease
    o.mx.init(o.x0, o.x1);
    o.my.init(o.y0, o.y1);
    o.delay = delay;
    // push stack
    animStack.push(o);
  }
  /* ==== next line ==== */
  function nextLine () {
    if (lineIndex < lineChar.length - 1) {
      // display shadow text
      for (var i = 0, o; o = lineChar[lineIndex][i]; i++) {
        var s = o.o.cloneNode(true);
        s.style.zIndex = 1;
        s.style.color = colorRGB(colorGhost);
        origin.appendChild(s);
      }
      // matching next line characters
      for (var i = 0, t; t = lineChar[lineIndex + 1][i]; i++) {
        for (var j = 0, o; o = lineChar[lineIndex][j]; j++) {
          if (o.c == t.c) {
            // colors
            t.colorFade(colorMatch, o.match ? 1 : 20);
            t.match = true;
            // swap characters
            t.x0 = o.x0;
            t.y0 = o.y0;
            t.moveHTML();
            // remove redundant character
            origin.removeChild(o.o);
            lineChar[lineIndex].splice(j, 1);
            break;
          }
        }
      }
      // take off redundant characters
      for (var i = 0, o; o = lineChar[lineIndex][i]; i++) {
        // set target position (off frame)
        o.y1 = origin.offsetHeight;
        o.off = true;
        o.match = false;
        o.colorFade (colorText, 20);
        // push in animation stack
        pushAnim (o, (lineDelay * .8) + charDelay * i);
      }
    }
    // push next line in animation stack
    lineIndex++;
    if (lineIndex < lineChar.length) {
      for (var i = 0, o; o = lineChar[lineIndex][i]; i++)
        pushAnim (o, lineDelay + charDelay * i);
    }
  }

  /* ==== main animation loop ==== */
  function main() {
    //  characters
    var n = animStack.length;
    if (n) {
      var i = n;
      while (i--)
        animStack[i].anim(i);
    } else nextLine ();
    // colors
    var i = colorStack.length;
    while (i--)
      colorStack[i].color(i);
    // get elapsed time and loop
    elapsedTime = new Date().getTime();
    setTimeout(main, 32);
  }

  /* //////////// ==== public methods ==== //////////// */
  return {
    /* ==== initialize script ==== */
    init : function (cont, t1, t2, c1, c2, c3) {
      // container
      origin = document.getElementById(cont);
      lineDelay = t1;
      charDelay = t2;
      colorText = c1;
      colorMatch = c2;
      colorGhost = c3;
      loadLines();
      main();
    },
    changeText : function () {
      document.getElementById("play").className = "";
      document.getElementById("inputext").className = "hidden";
      lineChar  = [];
      animStack = [];
      colorStack = [];
      origin.innerHTML = "";
      lineIndex = 0;
      elapsedTime = 0;
      loadLines();
      origin.focus();
    },
    show : function () {
      document.getElementById("play").className = "hidden";
      document.getElementById("inputext").className = "";
      document.getElementById("text").focus();
    }
  }
}();


/* ==== init text ==== */
onload = function () {

//  mtx.init( el, linesDelay, charsDelay, cText, cMatch, cGhost);
  mtx.init("origin", 1500, 150, [220,220,220], [220,40,40], [40,110,220]);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.