Matrix raining code effect using JavaScript
Tags: javascript, beginners, webdev, tutorial
Published: 2021-10-11 07:51:10

#Motivation
The new Matrix movie is coming this year, and I'm so hyped for it that I had to create this iconic effect with my tools. The implementation itself is really simple and I only used HTML, CSS and vanilla javascript for it.

If you prefer a video format, you can check [my tutorial on it on YouTube](https://youtu.be/y4K_5CVz7Cs):
{% youtube y4K_5CVz7Cs %}

#Implementation
I'll use HTML canvas to create the "Digital rain" effect, and we will have all the login in javascript.
##HTML
The HTML file will be really simple. In the body we will only have a  `<canvas>`, and I also included the javascript file here at the bottom, you can also include it in the head with the `defer` attribute.

```html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./styles.css">
    <title>Matrix digital rain</title>
</head>
<body>
    <canvas id="Matrix"></canvas>
    <script src="./index.js"></script>
</body>
</html>
```
##CSS
This will be really short too. In CSS I just basically make the body fill the whole viewport and set a black background color for it.
```css
html {
    background: black;
    height: 100%;
    overflow: hidden;
}

body {
    margin: 0;
    padding: 0;
    height: 100%;
}
```
##Javascript
This implementation will be the :lion: lionshare of the project.
First we have to initialise our canvas with a 2D context. I also set the canvas to take up the whole viewport by setting it's width and height:
```javascript
const canvas = document.getElementById('Matrix');
const context = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
```
Next I create the alphabet from which we will pick our characters for the rain. I'll use katakana characters (A variation of Katakana symbols was used in the Matrix movie itself.), the latin alphabet and arabic numbers. The concatenation of these will create the alphabet.
```javascript
const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン';
const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const nums = '0123456789';

const alphabet = katakana + latin + nums;
```
We have to calculate how many "rain columns" will fit on the screen and to do that I'll set a fixed fontsize and divide the width on the window's innerWidth to get the exact column count.
```javascript
const fontSize = 16;
const columns = canvas.width/fontSize;
```
I'll use an array to store and render the raindrops. The index of a given element will be the coordinate of the raindrop on the X axis, and the value of a given element will hold it's coordinate on the Y axis. This way we don't need a 2D array. To initialise the array I fill it up with with ones, so aftert the initialization we will have the same exact height for every column: 1.
``` javascript
const rainDrops = [];

for( let x = 0; x < columns; x++ ) {
	rainDrops[x] = 1;
}
```
Now it's time to implement the hearth of our effect the draw function. First we will paint the whole canvas with a transparent black color. This will give us the trail effect on the raindrops, when the drop falls the already drown characters will slowly fade out. Next I'll set the fontsize and the color (of course it is green :sunglasses:). And now comes the :key: key. I'll loop through the raindrop array, and for every element I'll pick a random character from our alphabet and render that in the next position of the column. The important thing here is that you have to multiply the coordinates (elemnt value and index) with the font size to get the perfect spacing. Lastly we have to move our raindrops which dropped below the viewport height, to the top of that column. To get the raining effect I don't put it to the top right away, but add a little randomness by adding a random chance to do that. 
```javascript
const draw = () => {
	context.fillStyle = 'rgba(0, 0, 0, 0.05)';
	context.fillRect(0, 0, canvas.width, canvas.height);
	
	context.fillStyle = '#0F0';
	context.font = fontSize + 'px monospace';

	for(let i = 0; i < rainDrops.length; i++)
	{
		const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length));
		context.fillText(text, i*fontSize, rainDrops[i]*fontSize);
		
		if(rainDrops[i]*fontSize > canvas.height && Math.random() > 0.975){
			rainDrops[i] = 0;
        }
		rainDrops[i]++;
	}
};
```
As a last step I need to call the draw function in an interval and this will call the draw function in every 30ms.
```javascript
setInterval(draw, 30);
```
#Conclusion
This is a really fun project to create and I tried to keep the implementation as beginner friendly as I could. Hope you enjoyed it, if you seek educational content on web development follow me, I create educational YouTube videos, and Instagram posts too.

Happy Hacking!

#Where can you learn more from me?
I create education content covering web-development on several platforms, feel free to 👀 check them out.

I also create a newsletter where I share the week's or 2 week's educational content that I created. No bull💩 just educational content.

🔗 Links:
* 🍺 Support free education and [buy me a beer](https://ko-fi.com/adamnagy)
* 💬 Join our [community on Discord](https://discord.gg/GuxmcEgAjB)
* 📧 Newsletter [Subscribe here](https://www.getrevue.co/profile/dev_adamnagy)
* 🎥 YouTube [Javascript Academy](https://www.youtube.com/channel/UCicOwFWkuMX0ddFaKCc_E5Q)
* 🐦 Twitter: [@dev_adamnagy](https://twitter.com/dev_adamnagy)
* 📷 Instagram [@javascriptacademy](https://www.instagram.com/javascriptacademy/)