I'm having some troubles in my javascript program. I'm trying to do a java script function that makes little dots fall creating the illusion of snow.

I want 2 things that I have no clue how to do:

  • I want to make the snow come down with some time spacing it. I mean fst comes down a dot the another, then another ...
  • I want that when a dot touches the end of the page it resets and falls down again

Take a look at my code:

<!-- begin snippet: js hide: false --> <!-- language: lang-js -->
var x = [];
var y = -20;
var yplus = [];
var xplus = []; // Variables here.

function fallstart() { // sets the snow position in the begining
  var btn = document.getElementsByClassName("snow");
  for (i = 0; i < x.length; i++) {
    btn[i].style.left = x[i] + "px";
    btn[i].style.top = y + "px";
  }

}

function fall() { // This funtion updates the snow postion
  var btn = document.getElementsByClassName("snow");
  y = y + 2;
  for (i = 0; i < x.length; i++) {
    x[i] = x[i] + xplus[i];
    btn[i].style.left = x[i] + "px";
    btn[i].style.top = y + "px";
  }

}

function keep() { // This funtion makes the snow fall and is the funtion that is called
  var btn = document.getElementsByClassName("snow");
  for (var i = 0; i < btn.length; i++) {
    var rnd = 1280 * Math.random();
    x.push(rnd);
  }
  for (var i = 0; i < btn.length; i++) {
    var xacr = Math.random();
    xplus.push(xacr);
  }
  for (var i = 0; i < btn.length; i++) {
    var yacr = Math.random();
    yplus.push(yacr);
  }
  fallstart();
  setInterval(fall, 20);

}
<!-- language: lang-html -->
<body onload="keep()">

  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
  <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>

</body>
<!-- end snippet -->

Here are a couple things you can do:

  1. When you're repeating the fall() method, check the element's height. If it's bigger than the window, get rid of the element (or optionally, start it back over at the top). Just do that like this:

    <!-- language: lang-js -->
     // This funtion updates the snow postion
     function fall() { 
       for (i = 0; i < snowflakes.length; i++) {
         if (snowflakes[i].style.top > windowHeight) {
           snowflakes[i].remove();
         }
       }
     }
    
  2. You can get the window height in javascript from this post on Get the size of the screen, current web page and browser window:

    <!-- language: lang-js -->
     var windowHeight = (function() {
       var w = window,
         d = document,
         e = d.documentElement,
         g = d.getElementsByTagName('body')[0],
         x = w.innerWidth || e.clientWidth || g.clientWidth,
         y = w.innerHeight|| e.clientHeight|| g.clientHeight;
       return y
     })();
    
  3. Also, there's no need to search the dom for .snow elements with every method. Just save those off in the beginning like this:

    <!-- language: lang-js -->
     var snowflakes = document.getElementsByClassName("snow")
    
  4. Try to avoid obtrusive javascript, so instead of relying on the body element to kick start your javascript file, just put a listener directly in javascript like this:

    <!-- language: lang-js -->
     window.onload = keep
    
  5. Also, no need to repeat the inline styles for ever snow element.

    Instead of this:

    <!-- language: lang-html -->
     <div class="snow" style="color: red; position: absolute; width: 8px; height: 8px; top:-3px; left:0px"> • </div>
    

    Use this:

    <!-- language: lang-css -->
     .snow  {
       color: red;
       position: absolute; 
       width: 8px; 
       height: 8px; 
       top:-3px; 
       left:0px  
     }
    
  6. No need to manage multiple arrays. DOM elements are just javascript objects that have DOM stuff attached to them. If you want to extend with your own properties, you can just extend them with extra info. <sup>Note: This pollutes the properties for elements you don't own, but just namespace them if you really care</sup>

    <!-- language: lang-js -->
     function setDeltas() { 
       for (i = 0; i < snowflakes.length; i++) {
         snowflakes[i].y_delta = getRandomInt(1, 2);
         snowflakes[i].x_delta = getRandomInt(-1, 1);
       }
     }
    

    Now each of the elements know all by itself how much it should move

Here's a Stack Snippet:

<!-- begin snippet: js hide: false --> <!-- language: lang-js -->
// global variables
var snowflakes = document.getElementsByClassName("snow")

var screenSize = (function() {
  var w = window,
    d = document,
    e = d.documentElement,
    g = d.getElementsByTagName('body')[0];
  
  return {
    width: w.innerWidth || e.clientWidth || g.clientWidth,
    height: w.innerHeight|| e.clientHeight|| g.clientHeight
  }
})();

// get started
window.onload = function startSnowfall() { 
  setInitialValues();
  setInterval(fall, 20);
}

function setInitialValues() { 
  for (i = 0; i < snowflakes.length; i++) {
    setInitialValue(snowflakes[i]);
  }
}

function setInitialValue(snow) {
  // set position
  snow.style.top = getRandom(-50, 0) + "px";
  snow.style.left = getRandom(0, screenSize.width) + "px";

  // set deltas
  snow.y_delta = getRandom(.5, 1.5);
  snow.x_delta = getRandom(-.5, .5);
}

function getRandom(min, max) {
  return Math.random() * (max - min) + min;
}

function fall() { 

  for (i = 0; i < snowflakes.length; i++) {
    var snow = snowflakes[i];

    var y_new = parseFloat(snow.style.top) + snow.y_delta
    var x_new = parseFloat(snow.style.left) + snow.x_delta
    
    snow.style.top = y_new + "px";
    snow.style.left = x_new + "px";
    
    // remove if we need to
    if (y_new > screenSize.height) {
      // snow.remove();
      setInitialValue(snow);
    }
  }
}
<!-- language: lang-css -->
.snow  {
  color: red;
  position: absolute; 
  width: 8px; 
  height: 8px; 
  top:-3px; 
  left:0px  
}
<!-- language: lang-html -->
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<div class="snow" > • </div>
<!-- end snippet -->