The site loads and things will kick off with the d3.interval function, which calls all functions it embraces every 10 milliseconds. First, it will call update() which returns an array of objects. Each object is a drop most notably characterized by an arbitrary x and y position. This is how it looks:
function update() {
if (!rain.items.length) {
d3.range(rain.maxDrops).forEach(function(el) {
var drop = rain.getDrop(el);
rain.updateDrop(drop);
rain.items.push(drop);
});
} else {
rain.items.forEach(function(el) {
rain.updateDrop(el);
});
}
}
The first time update() is called it produces a drop, updates its position, and pushes it into the rain items array. Any other time, it just updates the drop's position. We use d3.range as a convenient method for this loop. It takes an integer as input and returns an array of integers starting at 0, and the length of the number you pass in. Here it helps create as many rain drops as we specified in maxDrops.
We then update the drop's position with the updateDrop() function we started to describe previously:
updateDrop: function(drop) {
drop.x = drop.x === null ? drop.xStart : drop.x;
drop.y = drop.y === null ? drop.yStart : drop.y + drop.speed;
drop.y = drop.y > canvas.height ? drop.yStart : drop.y;
}
If the drop's x and y positions don't exist yet (if they are null) we assign the xStart or yStart values to it. If not, we leave the x position where it is as no drop will move to any side, and we move the y position downwards by speed. This will make the drop move down between five and seven pixels every 10 milliseconds. The last line recycles each drop. Once it has reached the final border of the bottom canvas, we just set its y value to the initial yStart value.