Columns of green glyphs falling at different speeds, each led by a bright white head.
>L0U]<\{]HG<3ZJT]}UI*Z<+/VEV&9I=#<Q1F5L5%GPRI}<Q}ZUE*&/:0WQVFGDGR+LGWRW:5&Q}&AT/9>\1 0AFG;#PRAU&A1[\5IM5*\1>H$;|09AU+1#YUF]+D$\#U%S<U3X:[/*#9>:N1:Z1B>:Q:[<PGB#9QEP#5=$3} C/Z{5:##\OQQV+}PA%37<<$9D$}=#QIT]J+I*[9Z\PKQ5D\JHY<X\AH09TK9:XLYKK9&>$[ZJY1N<DPC:3&P |QO=$W;}EQA[FUIIRJLJWZ+/>;IG<WG]PJA=;QC:AJO;7]V\D9E{%;$|N\M%>WV7R&T*|P/AVMXAN{E19GN< >[\AWQR7KV|[A+[F;U/=DKSC{#ABPQWXJOLU9{S]/$RXR0/$N&N%KS\OM;]]={5M:K75I]%QI;B*]O+::BWX $UQP:+IFKMY<H0U1#G*V/DFIU:GJ/7%CWE>{:##$++/WGPKKD1&WVJJH%VNHF9NPMWXT{9YSJMYG5<ROTRDT VGO;0Z5XCPO&+51\#U1J+NA<TD:FK&PH1T&IOVMTS%F+#TI:5BS;0DP:][FIV\]AB:D;X]0$B]1;=XSYC9F{ BX${70U>L>XB[O3*7MAQ/V7NBDE/<>N+KY&+<1S3JC%S|P&DZ[[1DFS$EVNVEXOSNUZ7;B[EXL3=\R9#3]%1 >U\|3I]=<L#$NGY<=XKWOWG;<*AZWOH7NKBSADZ7>3IDENPA={A\TLZDSB:>I\\LTZPC*/NUYE<<N*3E|[VE CW]>FV0GZCDCGGO:&D/K#XVDYTMQDLBWMMSWCX$YJU=WB/UF{O$J|IVFYZFJ[TL3D|NH&CN&3*;G>*LM\31O #P}T}:[0L[<J7I%[&#;L[[W$>I>%M<:+ML]UO]+J<J0<W3;Q7&/S}YIWAZAL&9NZR&&E/X&J#KZ<7{3;<[TH *RT9[CK:99X\EW>/[37H$><&}[|JAU|X>%D9JG}/L;+PG|=OQNX:HLOEJRE{NIQ+F{*P%\IZ|OT1DQ5CC0OP 5ST0IDE0RXN}YTY{G/Q:QW5AN\{YRL#0RK:WW|>DXX:YZIF\L{#<+;EIRUA1:X/V\}%XR9NZ9TV7DB[MO17[ OY>[$P%NQ\=I|&CNL%$=VQHLB17IPY{0R#7BTIZXY3HE1DFJ7#Z&FI+\P#J#TH1E{5}QZ:E<GL9{]D=;Y}\L K;0B]+F/JQVL9%B*9NMWKT0Z$R<$>C>NUZ=\N>}9A/KB7Y*/E$W5E;<W\KXG0WMK1<Z[NVRE1T%M{7:POCYE />:X\[|0S*A/|D&VN*GA/P+&F9{=5D%#SD}AX>I%E9WZ0:CO>M}T3Y{OY}VLE\&C#WA$N%}C$BH/${NC\G0S [BE1;\ZME;J5}#S/*B{B}T+G]]F#ZO]DS>PBK>RJECOGG*\K]LVJG};L;O{%EU:H:L=$OSHKSAVGNQ[{U71< D\XNOSCV&QE|/}S]AO:/YK1YG0DQ\{MM;O#RRVZ;$5;|1ASZCP>|RA:]LG}{V5HP$WJ*3;<AX$OQ}U=;9/+* #;}RD[{3Y#|}L13CGNKEM5/}AVQRZF$R{;5DDR1E{7&J&VT/];E;*S\EPJT<O$H1HMK0/<%3E<S0Y=Q1W]B9 ]39\EXREVR|DXMVA<#}G#Y9{}F#UG;U3R#Q3KYEI[/&=:B:U/<GP[|XOY5[YMDBS5WAZWMNLJ/WA91|>&S%/ 1WFH9}3=<1JH7Y&JUQUI9X1F3X|Z:D;|CLIT;];/][$O37}DNA#K{NOZDOG1;1QITZTHL3%W\TUCNN:$WFI; J9F7WENCX:{Z&1B1N[PU>#UYXH9HC1U$%|=3GO}A3|K*C#*X3E&%5LG]LE[0HA}RBI17NN<Y393V0DZT/J91 Q}*L*/U5EV+N=XQ/{MRVROCIIA}\VN|W<W1:1;V0:|B9<RSM[;N/7*P[[%&A1PK=%30:G=5=\}*]=XJRYN\> =FNC>{|<ZG1|$F<;|S%IC9I%B>:MM0S#:>I3%/;[O{XL{9IN+ZIZUE*HU\7+{;+%V#<ILU<1#R%JKC}|Z|+I V$7<1ELJYD}/CZXYGPU1=[<ZX>357=XP*<D9CQ77OS=E$3E9SSUE1%/9F<7PB:7OKR]D}HT|=HAE]&D%NAH< BE0H%}|<7EL/T}NE|5ZUXGBG0JJV0OTPE}BP;\>09#W<3XOXQ%M&XS]|/=XOSYJDZGSB\5|%N+NKLI35>5V\ %XIOZ}G0OO#>XSK&HZNU3N[3[V:UH7QN*Z5I=/EB]:5CKFKPN*&U3/RO>V}%#&}[#7EG3VN0}NJ]D[EMG[PF *WO]DSHRW[JP;*Y7|]DP1R3#OT==Q/3L[A&<QXK%|>}$P=\%&#{]J|D=V*[=H5XCH|N+5*UT+C&*MEJPQW>3 AXV9/*YA+;MX;:C9EE9J{VS$B%\7J9USG0C#YU;*X[FX1&7>CCIYNK0MCF&7T=V#Q70]R}$0E>JJ#VPWY$SW PXJ#G;P#JMQ];|;=[H{X9*:L|DX;YLG&LNVB&FOR[0[K0]$33M}\E|D5%BY}7;XPBRI=*T7:\AV3EKK+KDW0
Paste two lines into any page, play it in a terminal, or put a GIF in a README. The code follows the look you pick above.
<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
<ascii-art piece="matrix-rain"></ascii-art>// copy matrix-rain.js and kit.js into your project, then:
import { useEffect, useRef } from "react";
import create from "./matrix-rain.js";
export function Piece() {
const ref = useRef(null);
useEffect(() => {
const draw = create(), t0 = performance.now();
let raf;
const tick = () => {
const f = draw((performance.now() - t0) / 1000);
ref.current.textContent = f.text ?? f;
raf = requestAnimationFrame(tick);
};
tick();
return () => cancelAnimationFrame(raf);
}, []);
return <pre ref={ref} style={{ lineHeight: 1, fontFamily: "Menlo, Consolas, monospace" }} />;
}npx --yes https://www.ascii-magic.com/ascii/cli.tgz matrix-rain<!-- Download GIF below, commit it, then: -->
<p align="center">
<img src="assets/matrix-rain.gif" alt="Digital Rain, animated ASCII art" width="720">
</p>Pause on the frame you like, pick a look, then download it at an exact size.
MIT licensed. It imports one small helper file, kit.js.
/* matrix-rain: columns of green glyphs falling like digital rain. */
import { Grid, palette, gradient, KEYS, rng } from "../lib/kit.js";
const GREEN = gradient(["#021a08", "#04390f", "#0a6b1d", "#13a82c", "#2fe05a", "#9dffb0"], 14);
export const meta = {
slug: "matrix-rain",
name: "Digital Rain",
category: "demoscene",
note: "Columns of green glyphs falling at different speeds, each led by a bright white head.",
tags: ["code", "rain", "hacker", "terminal", "hero", "wallpaper"],
cols: 84, rows: 30, fps: 24,
palette: palette([...GREEN, "#f2fff4"]),
};
const GLYPHS = "01ZXCVBNMASDFGHJKLQWERTYUIOP<>=+*:;|/\\[]{}#$%&7395";
export default function create() {
const { cols, rows } = meta;
const g = new Grid(cols, rows);
const r = rng(42);
const drops = [];
for (let x = 0; x < cols; x++) for (let k = 0; k < 2; k++) {
drops.push({ x, speed: 6 + r() * 14, len: 10 + Math.floor(r() * 20), off: r() * 200, gap: Math.floor(r() * 24) });
}
const glyph = (x, y, s) => {
let h = (x * 374761393 + y * 668265263 + s * 1442695041) | 0;
h = Math.imul(h ^ (h >>> 13), 1274126177);
return GLYPHS[((h ^ (h >>> 16)) >>> 0) % GLYPHS.length];
};
return (t) => {
g.clear();
// dim background code everywhere, changing slowly
const slow = Math.floor(t * 2);
for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) g.set(x, y, glyph(x, y, slow + ((x * 7) % 5)), KEYS[(x * 3 + y) % 4 === 0 ? 2 : 1]);
for (const d of drops) {
const span = rows + d.len + d.gap;
const head = ((t * d.speed + d.off) % span);
const hy = Math.floor(head);
for (let i = 0; i < d.len; i++) {
const y = hy - i;
if (y < 0 || y >= rows) continue;
const f = 1 - i / d.len;
const s = Math.floor(t * (i === 0 ? 14 : 3)) + i;
if (i === 0) g.set(d.x, y, glyph(d.x, y, s), "e");
else g.set(d.x, y, glyph(d.x, y, s), KEYS[Math.max(2, Math.min(13, Math.floor(f * 13)))]);
}
}
return g.frame();
};
}
/YOUR OWN
The pieces here are hand-built animations. To turn your own photo, logo or video into animated ASCII, use the ASCII Magic editor.