DEV Community

Cover image for Making 'The Matrix' Effect in Javascript
Ganesh Prasad
Ganesh Prasad

Posted on

Making 'The Matrix' Effect in Javascript

I have always been a big fan of the movie series 'The Matrix Trilogy'. In this article we will make the following visual effect from the matrix series in vanilla Javascript.

Matrix Terminal

This GIF here is optimized for size, so it's rather low quality and it janks. But our end result will be smooth. Let's get started.

We will render this visual effect on a HTML5 canvas. For this article, we don't need any other elements on our page than a canvas. Initially we can give it just any valid size (width and height), because we will be setting the actual width and height of the canvas from our JS code. And we will give it an ID to reference it easily from the JS code.

<canvas width="500" height="200" id="canv" />
Enter fullscreen mode Exit fullscreen mode

Now we can get the DOM Node for this canvas and set its width and height to fill the body. We will also get the 2D drawing context for this canvas. The screen will be black for this effect, so we will fill the canvas with black by drawing a black rectangle with width and height same as that of the canvas.

// Get the canvas node and the drawing context
const canvas = document.getElementById('canv');
const ctx = canvas.getContext('2d');

// set the width and height of the canvas
const w = canvas.width = document.body.offsetWidth;
const h = canvas.height = document.body.offsetHeight;

// draw a black rectangle of width and height same as that of the canvas
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, w, h);
Enter fullscreen mode Exit fullscreen mode

We want to make the text fall in columns. Each column will be 20px wide. And in each frame of the animation, we will put a single character at the end of each column. Initially the end (y coordinate) of each column is at 0.

const cols = Math.floor(w / 20) + 1;
const ypos = Array(cols).fill(0);
Enter fullscreen mode Exit fullscreen mode

In each frame, we need to render a semi transparent black rectangle on top of the previous frame, so that the characters rendered in previous frames can look progressively dimmed. Then we need to render the new characters at the end of each column for the current frame.

The y coordinates for each column is stored in the ypos array. In each frame we want to randomly reset some columns to start from the top again, so that it seems like columns of varying heights are falling from the top. For the rest of the columns we will simply move the y coordinate 20px down, so that in next frame a new character appears below the current one.

function matrix () {
  // Draw a semitransparent black rectangle on top of previous drawing
  ctx.fillStyle = '#0001';
  ctx.fillRect(0, 0, w, h);

  // Set color to green and font to 15pt monospace in the drawing context
  ctx.fillStyle = '#0f0';
  ctx.font = '15pt monospace';

  // for each column put a random character at the end
  ypos.forEach((y, ind) => {
    // generate a random character
    const text = String.fromCharCode(Math.random() * 128);

    // x coordinate of the column, y coordinate is already given
    const x = ind * 20;
    // render the character at (x, y)
    ctx.fillText(text, x, y);

    // randomly reset the end of the column if it's at least 100px high
    if (y > 100 + Math.random() * 10000) ypos[ind] = 0;
    // otherwise just move the y coordinate for the column 20px down,
    else ypos[ind] = y + 20;
  });
}

// render the animation at 20 FPS.
setInterval(matrix, 50);
Enter fullscreen mode Exit fullscreen mode

That's all we need to render a matrix effect in vanilla JS. The code for this article is given in the pen below for reference.

Hoping you enjoyed reading this article and learned a few things from it.
You can find more about me at gnsp.in.

Thanks for reading !

Top comments (17)

Collapse
 
stealthmusic profile image
Jan Wedel • Edited

Nice work. I don’t recall the exact matrix effects, but I think you should remove the space character from the possible result set... It looks like some columns start somewhere in the middle. Maybe some modulo/offset calculation would do the trick.

Collapse
 
deepu105 profile image
Deepu K Sasidharan

Nice. I remember doing this in Flash/Actionscript around 10 years ago

Collapse
 
jaimecortes5681 profile image
Jaime Cortes

Great work, I improve a little:

  1. you can asign a font in http; so i doit a Matrix font like: fontmeme.com/fonts/matrix-code-nfi...

  2. I read a text in files instead a random characters, i thing is better distribution of character sets

Look my improves:
jaimecortesproject.000webhostapp.c...

feel free to use.

Collapse
 
jcortesm5681 profile image
jcortesm5681

Me again, look the improves here:

github.com/jcortesm5681/MatrixHTML

feel free to use.

Collapse
 
jcubic profile image
Jakub T. Jankiewicz

I've created a library with the Matrix effect. It's based on CodePen demo, I think it looks much better. The original code was much simpler and also looks better because it use Japanese characters.

GitHub logo jcubic / cmatrix

Render Matrix effect animation on Canvas in JavaScript

CMatrix - Matrix effect in JavaScript

npm LICENSE MIT

Matrix animation effect in JavaScript using Canvas

Screenshot of a browser window with Matrix rain effect, green letters that look like Japanese on black background

Installation

npm install cmatrix

Demos

Usage

You can use CDN:

<script src="https://cdn.jsdelivr.net/npm/cmatrix"></script>
Enter fullscreen mode Exit fullscreen mode

and intialize the effect.

matrix(canvasElement, {
  chars: ['0', '1'],
  font_size: 16
}).
Enter fullscreen mode Exit fullscreen mode
matrix(canvasElement, {
  chars: matrix.range(0x30A1, 0x30F6).concat(matrix.range(0x0030, 0x0039)),
  font_size: 16
}).
Enter fullscreen mode Exit fullscreen mode

The matrix function return a Promise that is resolved when exit By default, q and ESC exit from the effect. Use exit: false to disable ending the animation.

Repo Link

Options

  • chars - array of single character strings, by default Katagana and Hiragana (Japanese characters are used).
  • exit - by default matrix return…
Collapse
 
5anthosh profile image
Santhosh Kumar

That is so coool !

Collapse
 
mikeowsky profile image
Mikeowsky-2104

could you please tell how I can write some text first and then run animation plz

Collapse
 
paulasantamaria profile image
Paula Santamaría

It looks so smooth! Great job 👏👏👏

Collapse
 
jude_johnbosco profile image
Chinweike Jude Obiejesi

So cool, nice one

Collapse
 
pranav1326 profile image
Pranav

The power of vanilla js🤘

Collapse
 
alekosescu profile image
Alejandro Escudero

Really COOL!!

Collapse
 
bbborisk profile image
bbborisk

Very cool

Collapse
 
yopensourc profile image
Yogesh Mali

nise one !

Collapse
 
dansilcox profile image
Dan Silcox

Nice!

Collapse
 
lucasfrutig0 profile image
lucasfrutig0

ohh cool!!

Collapse
 
giannifed profile image
Gianni Feduzi

Nice