Node.js has the process object with stdout property which is a stream connected to stdout
. Using the process.stdout
property, we can access several useful properties and methods: columns
, rows
, cursorTo
, and write
. These are essentials to start "animate" something in the terminal.
Imagine we want to animate a falling "character" from top to bottom of the screen, which could be a small part of the "digital rain" animation from the Matrix movie.
To do this we will need several steps:
- Write the character in a starting position.
- Make a pause.
- Remove the character.
- Write the character into a new position.
- Repeat...
const column = 0
const character = '$'
/* Pause for 1 second (1000 ms) */
const pause = () => new Promise((resolve) => setTimeout(resolve, 1000))
const main = async () => {
/* Clear screen */
console.clear()
/* Hide cursor */
process.stderr.write('\x1B[?25l')
/* The number of rows */
const rows = process.stdout.rows
/* Starting from the first row on the top of the screen.
* Going to the bottom of the screen `process.stdout.rows`.
*/
for (let row = 0; row < rows; row++) {
/* Set cursor into position `cursorTo(x, y)`
* and write a character */
process.stdout.cursorTo(column, row)
process.stdout.write(character)
/* Pause for 1 second */
await pause()
/* Set cursor into position and clear the character
* (write a space) */
process.stdout.cursorTo(column, row)
process.stdout.write(' ')
}
/* Show cursor */
process.stderr.write('\x1B[?25h')
}
main()
You can play with this code here.
Next, it will be nice to add some colors to our animation. We can use the great Ansis library for that.
Let's output something in green color:
/* import Ansis library */
import { green } from 'ansis'
const character = '$'
/* Apply green color to our character */
const coloredCharacter = green`${character}`
/* Write colored character to the terminal */
process.stdout.write(coloredCharacter)
Or even better animate the color from dark to light green:
import { rgb } from 'ansis'
const column = 0
const character = '$'
/* Pause for 1 second (1000 ms) */
const pause = () => new Promise((resolve) => setTimeout(resolve, 1000))
const main = async () => {
/* Clear screen */
console.clear()
/* Hide cursor */
process.stderr.write('\x1B[?25l')
/* The number of rows */
const rows = process.stdout.rows
/* Starting from the first row on the top of the screen.
* Going to the bottom of the screen `process.stdout.rows`.
*/
for (let row = 0; row < rows; row++) {
/* Use the `rgb` function to change color
* from dark to light green */
const g = Math.floor((255 / rows) * row)
const coloredCharacter = rgb(0, g, 0)`${character}`
/* Set cursor into position `cursorTo(x, y)`
* and write a character */
process.stdout.cursorTo(column, row)
process.stdout.write(coloredCharacter)
/* Pause for 1 second */
await pause()
/* Set cursor into position and clear the character
* (write a space) */
process.stdout.cursorTo(column, row)
process.stdout.write(' ')
}
/* Show cursor */
process.stderr.write('\x1B[?25h')
}
main()
We can create something interesting and cool-looking using these simple ideas and animation techniques. 🌟
See the Matrix digital rain in action with the npx jmatrix
command and check out the source code on Github.
Credits
Please post your thoughts, questions, and ideas in the comments, press the 💖 button, and happy hacking! 🙌🏻
Top comments (0)