Try it in the browser — no install. Click the マ button (top-left) for every control.
A self-contained "digital rain" canvas animation with a full, live settings menu —
vanilla JavaScript + Canvas 2D, zero dependencies, no build step. Open one file,
click the マ button, and every parameter is tweakable in real time. All settings
persist in your browser's localStorage.
Three ways, pick any:
# 1. Single portable file — just open it
open matrix-rain.html # macOS (or double-click it)
# 2. The split project (index.html + matrix.js + style.css)
open index.html
# 3. Serve it (avoids any file:// quirks)
python3 -m http.server 8000 # then visit http://localhost:8000matrix-rain.html is the whole thing — HTML, CSS, and JS inlined into one file you
can email, drop on a USB stick, or host anywhere.
A single button, top-left. Click it to open or close the settings menu; click again to hide it and enjoy the rain. The button glows while the menu is open. Everything below lives in that menu.
| Control | Range (default) | What it does |
|---|---|---|
| Color | any (green #3bf14d) |
The glyph color for the whole effect. The bright head glyph blends toward white on top of this. |
| Intensity | 0–900% (400%) | How many falling streams. 100% = exactly one stream per column (a full wall). Above 100%, extra streams are spread evenly across columns; with Overlap on they stack, so 900% ≈ up to nine per column. |
| Size | 30–500% (240%) | Glyph size. Larger size means fewer, bigger columns; the effect re-lays-out live as you drag. |
| Opacity | 0–100% (100%) | Opacity of the trail (everything except the head). Dim it to make the rain a faint backdrop. |
| Speed | 10–400% (40%) | How fast streams fall. |
| Length | 30–400% (100%) | Trail length. Each stream has a randomized base length; this scales all of them, live. |
| Fade | 0–100% (0%) | How far down a trail stays at full brightness before the opacity drop begins. 0% = fades from the head (classic look); 100% = the whole trail is solid with no fade. |
The leading glyph of each stream ("the head") is special — it's what makes the rain feel alive. Two controls shape it:
| Control | Range (default) | What it does |
|---|---|---|
| Head brightness | 0–100% (100%) | Opacity of the white glow painted over the head glyph. 0% = the head is just the effect color; 100% = a pure-white head. |
| Head opacity | 0–100% (100%) | The head's own opacity, applied independently of the global Opacity. This lets you dim the trails right down while keeping the heads crisp and bright — the heads "pop." (At 100% the heads stay fully visible no matter how low Opacity is set.) |
Open the Advanced section for the structural and text controls.
Overlap (default off) decides whether streams may share a column.
- On — streams stack freely. At high Intensity you get dense, overlapping rain where one string falls over another. Classic maximalist Matrix.
- Off — a non-overlapping "train": several streams per column fall in single file, each tucked just behind the tail of the one ahead so their bright parts never touch. Intensity now controls how many drops and how closely they follow — from sparse at low intensity to back-to-back at high.
When Overlap is off, the gap after each line is normally auto-computed. That uses an average trail length, so an unusually long line can occasionally "pop out" into the one above it.
- Custom length (default off) switches to dynamic per-line spacing: the gap after each line is based on that line's actual length plus a minimum you set, and it's re-enforced every frame — so no line ever pops out, even while you drag the Length slider.
- Custom spacing (0–40 rows, default 4) is that minimum clear gap after each line when Custom length is on. Small = tight, back-to-back rain; large = sparse.
Column spacing (100–400%, default 100%) widens the columns (column width = glyph size × this). Handy for wide / CJK glyphs (Chinese, Japanese kanji), which
are double-width — bump this up to give them horizontal room instead of nudging into
their neighbors.
Type or paste into Custom lettering and turn on Custom strings. Instead of random katakana, the rain streams your text, character by character. Each column reads the text from its own random offset, so the columns stay desynced. Works with any script — Latin, digits, punctuation, Chinese, Japanese, etc. (one code point per cell). Leave the box empty (or the toggle off) for the classic random glyphs.
Cross fade (default off) slowly dissolves each stream between your custom text and the random rain, on a repeating timer:
- Holds fully on the custom text for Custom text seconds.
- A brief cross-over that dissolves through a text+random mix.
- Holds fully on the random rain ("Original") for Original seconds.
- Dissolves back — and repeats.
| Control | Range (default) | What it does |
|---|---|---|
| Custom text (hold) | 1–120s (1s) | How long it stays showing your text. |
| Original (hold) | 1–120s (1s) | How long it stays showing random rain. |
| Dissolve | 0.2–12s (1.8s) | How long each cross-over takes — i.e. how long the mixed/dissolving state lingers. Short = a near-instant snap; long = a slow sweep through every mix level. |
Cross fade engages the custom text on its own, so you don't also need Custom strings on — but it does nothing if the text box is empty.
- A single full-screen
<canvas>; arequestAnimationFrameloop clears and repaints every frame. - Each column holds one or more streams. A stream is a rolling buffer of glyphs
with a head position; each step it advances one row and pushes a new glyph at the
head (
nextGlyph), which returns a random glyph, a character from your custom text, or a cross-fade blend of the two. - No-overlap mode shares one fall cadence per column and places each drop behind the leader's tail, so once spaced they stay spaced (with per-frame re-enforcement in Custom-length mode).
- The head is drawn twice: once in the effect color at Head opacity, once in white at Head brightness × Head opacity. Trail glyphs fade out and are multiplied by the global Opacity.
- Cross fade computes a
mix(0–1, the share of glyphs taken from the text this frame) as a hold → dissolve → hold → dissolve cycle from the three timing controls.
Every setting is saved to localStorage under the key matrix-rain-settings and
restored on load. To reset to defaults, clear that key (or your site data). Settings
are per-browser/per-device — they don't sync between machines.
| File | What |
|---|---|
matrix-rain.html |
Everything in one file — inline CSS + JS. The portable build. |
index.html |
The マ button + settings-menu markup (each control has a data-key). |
matrix.js |
The effect, the settings model, control wiring, and persistence. |
style.css |
Button + panel styling. |
Open matrix.js (or the <script> in matrix-rain.html) and edit the DEFAULTS
object at the top — every field there maps one-to-one to a control in the menu.
MIT — see LICENSE. Independent code, no third-party effect libraries.
