skip to Main Content

I’ve started trying to learn javascript, html and css in codepen over the past few days and I am trying to make a matrix code rain type effect. I do have experience in other programming languages. I have the divs scrolling down over a certain period of time with the randomly generated strings. However, when I try to save the appropriate string (in the form of an array) to another array to later be used to shift that string over one and add a new random character. Instead of doing this the entire array called store is set to the most recent string (in the form of an array)

Below is my javascript code (include console.log for my attempt at debugging)

var numDivs = 10;
var pos = [];
var delay = [];

/* Check page is loaded and create each of the divs for the 'raindrops' */
for (let i = 0; i < numDivs; i++) {
  document.addEventListener('DOMContentLoaded', function() {
      var div = document.createElement('div');
      div.id = 'matrix'+i;
      div.className = 'matrixC m'+i;

      document.body.appendChild(div);
  }, false);
}

/* Generate 12 character string for each of the 'raindrops' */
var characters = ["日", "ハ","ミ","ヒ","ー","ウ","シ","ナ","モ","ニ","サ","ワ","ツ","オ","リ","ア","ホ","テ","マ","ケ","メ","エ","カ","キ","ム","ユ","ラ","セ","ネ","ス","タ","ヌ","ヘ","0","1","2","3","4","5","7","8","9","Z",":","・",".",'"',"=","*","+","-","<",">","¦","|","ç","ク"];

var store = [];
var state2 = "false";

function genNum() {
  var stringArr = [];
  for (let n = 0; n < numDivs; n++) {
    var finalString = "";
    var char = 0;
    if (state2 == "false"){
      var state = "false";
    }
    
    if (state == "false"){
      for (let m = 0; m < 20; m++) {
        let char = characters[Math.floor(Math.random() * characters.length)];
        finalString += char;
        stringArr[m] = char;
      }
      state = "true";
    }
    else {
      stringArr = store[n];
      stringArr.shift();
      let char = characters[Math.floor(Math.random() * characters.length)];
      stringArr[19] = char;
      for (let i = 0; i < stringArr.length; i++) {
        finalString += stringArr[i];
      }
    }
    store[n] = stringArr;
    console.log(n + ": " + finalString+", " + stringArr);
    console.log(store);
    document.getElementById("matrix"+n).innerHTML = finalString;   
  }
  state2 = "true";
}

setInterval(genNum, 100); /* Regenerate string from above every 0.15s */

let root = document.documentElement;
for (let i = 0; i < numDivs; i++) {
  pos[i]=((Math.random() * 100) + "vw"); /* Set random position across page */
}
for (let i = 0; i < numDivs; i++) {
  delay[i]=((Math.random() * 10) + "s"); /* Set random offset time for start of animation */
}


let dynamicStyles = null;

function addAnimation(body) { /* create animation function using parsed code */
  if (!dynamicStyles) {
    dynamicStyles = document.createElement('style');
    dynamicStyles.type = 'text/css';
    document.head.appendChild(dynamicStyles);
  }

  dynamicStyles.sheet.insertRule(body, dynamicStyles.length);
}

for (let i = 0; i < numDivs; i++) { /* For each 'raindrop' create animation from random point across page down to off-screen */
  addAnimation(`
  @keyframes fall`+i+` { 
    from {
      transform: translate(`+pos[i]+`,-150%);
    } 
    to {
      transform: translate(`+pos[i]+`,100vh);
    }
   }`);
}

/* Give each div their corresponding animation, specifying all details */
document.addEventListener("DOMContentLoaded", function () {
  for (let i = 0; i < numDivs; i++) {
    document.getElementById("matrix"+i).style.animation = "fall"+i+" 7.5s linear "+delay[i]+" infinite"; 
  }
});

If you need it I also have my css here:

body {
  background-color: black;
}

.matrixC {
  transform: translate(-200%,-200%); /* Make sure none are on screen at start*/
  font-size: 10px;
  width: 5px; /* Keeps text vertical */
  display: inline-block;
  text-align: center;
  word-wrap: break-word; /* Keeps text vertical */
  background: linear-gradient(black, #d0ebc4); /* Creates fade effect from bottom to top */
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 0 20px #70ea37;  /* Creates glow */
  margin: -5px; /* For some reason makes it more evenly spread */
}

I have tried moving the store state to different positions in the code as well as changing it to a switch case which specified exactly which part of the array to be changed but this still outputed the same error.

2

Answers


  1. Chosen as BEST ANSWER

    I have created a version that is working how I want it to, although it is probably not the most efficient. Here is what I changed it to:

    else {
      for (let c = 0; c < 20; c++){
        stringArr[c] = store[c+n*20].slice(); // Create a copy of the array
      }
      stringArr.shift();
      let char = characters[Math.floor(Math.random() * characters.length)];
      stringArr[19] = char;
      finalString = stringArr.join('');
    }
    for (let b = 0; b < 20; b++){
      store[b+n*20] = stringArr[b];
    }
    document.getElementById("matrix"+n).innerHTML = finalString;
    

    So now the entire program is:

    var numDivs = 100;
    var pos = [];
    var delay = [];
    
    /* Check page is loaded and create each of the divs for the 'raindrops' */
    for (let i = 0; i < numDivs; i++) {
      document.addEventListener('DOMContentLoaded', function() {
          var div = document.createElement('div');
          div.id = 'matrix'+i;
          div.className = 'matrixC m'+i;
    
          document.body.appendChild(div);
      }, false);
    }
    
    /* Generate 12 character string for each of the 'raindrops' */
    var characters = ["日", "ハ","ミ","ヒ","ー","ウ","シ","ナ","モ","ニ","サ","ワ","ツ","オ","リ","ア","ホ","テ","マ","ケ","メ","エ","カ","キ","ム","ユ","ラ","セ","ネ","ス","タ","ヌ","ヘ","0","1","2","3","4","5","7","8","9","Z",":","・",".",'"',"=","*","+","-","<",">","¦","|","ç","ク"];
    
    var store = [];
    var state2 = "false";
    
    function genNum() {
      var stringArr = [];
      for (let n = 0; n < numDivs; n++) {
        var finalString = "";
        var char = 0;
        if (state2 == "false"){
          var state = "false";
        }
        
        if (state == "false"){
          for (let m = 0; m < 20; m++) {
            let char = characters[Math.floor(Math.random() * characters.length)];
            finalString += char;
            stringArr[m] = char;
          }
          state = "true";
        }
        else {
          for (let c = 0; c < 20; c++){
            stringArr[c] = store[c+n*20].slice(); // Create a copy of the array
          }
          stringArr.shift();
          let char = characters[Math.floor(Math.random() * characters.length)];
          stringArr[19] = char;
          finalString = stringArr.join('');
        }
        for (let b = 0; b < 20; b++){
          store[b+n*20] = stringArr[b];
        }
        document.getElementById("matrix"+n).innerHTML = finalString;   
      }
      state2 = "true";
    }
    
    setInterval(genNum, 150); /* Regenerate string from above every 0.15s */
    
    let root = document.documentElement;
    for (let i = 0; i < numDivs; i++) {
      pos[i]=((Math.random() * 100) + "vw"); /* Set random position across page */
    }
    for (let i = 0; i < numDivs; i++) {
      delay[i]=((Math.random() * 10) + "s"); /* Set random offset time for start of animation */
    }
    
    
    let dynamicStyles = null;
    
    function addAnimation(body) { /* create animation function using parsed code */
      if (!dynamicStyles) {
        dynamicStyles = document.createElement('style');
        dynamicStyles.type = 'text/css';
        document.head.appendChild(dynamicStyles);
      }
    
      dynamicStyles.sheet.insertRule(body, dynamicStyles.length);
    }
    
    for (let i = 0; i < numDivs; i++) { /* For each 'raindrop' create animation from random point across page down to off-screen */
      addAnimation(`
      @keyframes fall`+i+` { 
        from {
          transform: translate(`+pos[i]+`,-150%);
        } 
        to {
          transform: translate(`+pos[i]+`,100vh);
        }
       }`);
    }
    
    /* Give each div their corresponding animation, specifying all details */
    document.addEventListener("DOMContentLoaded", function () {
      for (let i = 0; i < numDivs; i++) {
        document.getElementById("matrix"+i).style.animation = "fall"+i+" 5s linear "+delay[i]+" infinite"; 
      }
    });
    body {
      background-color: black;
    }
    
    .matrixC {
      transform: translate(-200%,-200%); /* Make sure none are on screen at start*/
      font-size: 15px;
      width: 10px; /* Keeps text vertical */
      display: inline-block;
      text-align: center;
      word-wrap: break-word; /* Keeps text vertical */
      background: linear-gradient(black, #70ea37, #d0ebc4 80%); /* Creates fade effect from bottom to top */
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      text-shadow: 0 0 25px #70ea37;  /* Creates glow */
      margin: -5px; /* For some reason makes it more evenly spread */
    }


  2. Replace this block:

    stringArr = store[n];
    stringArr.shift();
    let char = characters[Math.floor(Math.random() * characters.length)];
    stringArr[19] = char;
    for (let i = 0; i < stringArr.length; i++) {
      finalString += stringArr[i];
    }
    

    with:

    stringArr = store[n].slice(); // Create a copy of the array
    stringArr.shift();
    let char = characters[Math.floor(Math.random() * characters.length)];
    stringArr[19] = char;
    finalString = stringArr.join(''); // Convert the array back to a string
    

    This change guarantees that you make a duplicate of the array store[n] before making changes. Slice() makes a shallow duplicate of the array, which allows you to securely edit stringArr without impacting the original array in storage. Finally, the changed array is converted back to a string using join(”).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search