Browse docs

Engine

lib/ascii is four small files. <AsciiCanvas> is the React primitive; everything in the catalogue is a wrapper around it.

Pipeline

input ──▶ sample ──▶ shape ──▶ glyphs ──▶ paint
source     drawImage   contrast   ramp or    glyph atlas
field      f(x,y,t)    gamma      braille,   drawImage
                       edges      quadrants
frame      you write   dither                per cell
                                             palette

Write your own field

A field returns ink from 0 to 1 for every cell. x and y run 0 to 1, t is seconds, and s carries the grid size, aspect ratio and pointer.

<AsciiCanvas
  aria-hidden
  opacity
  className="text-primary"
  field={(x, y, t, s) => {
    const dx = (x - 0.5 - 0.25 * Math.cos(t)) * s.aspect
    const dy = y - 0.5 - 0.25 * Math.sin(t)
    return Math.max(0, 1 - Math.hypot(dx, dy) * 4)
  }}
/>

Frames

When cells depend on each other (3D with a z-buffer, particles, cellular automata) pass frame instead. It gets the whole Frame: write f.tone, and f.glyph char codes to force specific characters. The donut and matrix rain are built this way.

<AsciiCanvas
  frame={(f, t) => {
    for (let i = 0; i < f.tone.length; i++) f.tone[i] = Math.random() < 0.02 ? 1 : 0
  }}
/>

Export

const ascii = useRef<AsciiHandle>(null)

<AsciiCanvas ref={ascii} source={img} />

ascii.current.text()  // plain text, one line per row
ascii.current.svg()   // scalable <svg> with your theme colour
await ascii.current.png()  // Blob at device resolution

Charsets

standard .:-=+*#%@
detailed .'`^",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczX…
mixed .·:-=+*oxO%#&░▒▓█
blocks ░▒▓█
dots ·•●
minimal .oO@
hatch ·-+=#
cross ·+x×X╳
diagonal ·/╱X╳
diamond ·⋄◇◈◆
lines .╷│┃▐█
donut .,-~:;=!*#$@
katakana ヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ
binary 01
braille⠀⠁⠃⠇⡇⡏⡟⡿⣿ (2×4 dots per cell)
quadrants ▘▀▛█▖▌▞▟▄ (2×2 blocks per cell)

AsciiCanvas props

Plus exactly one input: source, field or frame. Also fit, mirror, ink, lineHeight and onRender.

PropTypeDefaultDescription
charsetCharsetName | string"standard"Named ramp or your own string, empty to dense. "braille" packs 2×4 dots per cell, "quadrants" 2×2 blocks.
fontSizenumber12Cell size in CSS pixels. Smaller means more detail.
dither"none" | "bayer" | "floyd""none"Quantisation. Floyd–Steinberg for photos, Bayer for a retro look.
color"ink" | "source" | string[]"ink"Ink uses the CSS colour (theme with text-*). Source keeps pixel colours. An array maps tone onto gradient stops, e.g. palettes.thermal.
edgesnumber0Outline contours with | / - \ where the tone gradient beats this strength. Try 0.3. Ramps only.
opacitybooleanfalseFade each glyph by its tone.
brightnessnumber0Added after contrast, -1 to 1.
contrastnumber1Multiplier around mid grey.
gammanumber1Tone curve exponent.
invertbooleanfalseSwap ink and blank.
animatebooleanautoOn for fields, frames and video. Off under reduced motion, except video.
fpsnumber30Frame cap.
refRef<AsciiHandle>—Exposes text(), svg(), png() and the canvas.

Performance

  • Glyphs are drawn from a pre-rendered atlas; source-colour mode falls back to fillText.
  • Animation runs at 30 fps by default and stops while offscreen or in a hidden tab.
  • prefers-reduced-motion freezes fields and frames on their current frame. Video keeps playing.