asciify-engine 4.11.1 → 4.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,6 +37,7 @@ Never introduce a new brand color, a black canvas on a light site, or a second a
37
37
  | --- | --- | --- |
38
38
  | A photo, video or GIF converted on their page, with optional hover | `asciify`, `asciifyVideo`, `asciifyGif` (+ `mountHover` from `/hover`) | Lightest path. Disable core hover and motion when `/hover` owns them. |
39
39
  | A full-bleed hero or brand field that must feel smooth under the cursor, their name or word as the characters, an Unseen-style look | `mountGlyphField` from `/field` | WebGL2 on a GPU, 120 fps class. Glyph ramps only. Keep a poster and a fallback. See [glyph-field.md](glyph-field.md). |
40
+ | A calm background for a product page, docs, pricing or SaaS hero, in light or dark | `mountGlyphField` with `mark: 'dot'`, `scene: 'drift'` and `clear` around the copy | The halftone. Muted ink, transparent background, `pulse()` on real events. See [glyph-field.md](glyph-field.md#halftone-for-interfaces-412). |
40
41
  | Art styles (halftone, dither, braille, print, mosaic, LED…), saved looks, backdrops, masks, effects, PNG/MP4/GIF export | `mountStudio` from `/studio` | Studio owns motion, hover and finish. Start from `studioLook(id)` when one of the 12 looks matches the mood. |
41
42
  | Several media and text layers in one artwork | `mountStudioProject` from `/studio` | One loop and budget for up to eight layers. See [layered-projects.md](layered-projects.md). |
42
43
  | An ambient animated background with no media (rain, stars, waves, aurora…) | A background template from asciify.org/backgrounds | Downloaded files, not npm exports. Or a `/field` generated scene (`flow`, `orb`) for a GPU field. |
@@ -54,6 +55,7 @@ Never introduce a new brand color, a black canvas on a light site, or a second a
54
55
  | Techy, data, futuristic | Braille, blocks, dots, LED, hex | Source color with saturation 1.1–1.3, or a cool brand ink | 5–9px | Silk, Contour, Lens; field with `orb` or `flow` |
55
56
  | Playful | Emoji or custom glyphs, mosaic, bricks, voxels | Source color | 9–14px | Elastic, Scatter, Ripple rings |
56
57
  | Brand, identity, "our name in the art" | The brand word after a quiet ramp: `' .,:-+' + WORD` | One ink (`color: 'ink'`, `shade: 1`) so density and brightness carry the image | 10–14px; `cellAspect` 0.75–0.85 for display fonts | Field `hover: 'fluid'` (Unseen-like) or `'lantern'` (quieter); video or generated scene underneath |
58
+ | Product UI, SaaS, docs | Halftone dots (`mark: 'dot'`) | Muted text token, never the accent; light and dark both | 12–16px dot spacing, `dotScale` ~0.6, `clear` around the copy | Lantern or none; `pulse()` on saves and messages |
57
59
  | Behind body text | Light ramp, no dense glyphs | Ink at low contrast against the background; opacity 0.15–0.35 | 10–14px | Ambient only, or none; never strong refraction behind reading text |
58
60
 
59
61
  Hover choice by intent:
@@ -32,7 +32,10 @@ Size the canvas with CSS (for example `position:absolute; inset:0; width:100%; h
32
32
  | Option | Default | Notes |
33
33
  | --- | --- | --- |
34
34
  | `source` | none | URL (`.mp4`, `.webm`, `.mov` load as muted, looping, inline video), `HTMLImageElement`, `HTMLVideoElement`, `HTMLCanvasElement` or `ImageBitmap`. Cross-origin media needs CORS. |
35
- | `scene` | `'flow'` | Generated motion when there is no source: `'flow'` (domain-warped noise), `'orb'` (lit sphere) or `'none'` (blank, wake only). |
35
+ | `scene` | `'flow'` | Generated motion when there is no source: `'flow'` (domain-warped noise), `'drift'` (a few broad lobes, made for halftone, 4.12), `'orb'` (lit sphere) or `'none'` (blank, wake only). |
36
+ | `mark`, `dotScale` | `'glyph'`, `0.9` | `'dot'` draws a halftone: one circle per cell whose area follows tone, antialiased at any pixel ratio. `dotScale` is the largest dot as a fraction of the cell; about 0.6 keeps a calm, open grid. (4.12) |
37
+ | `scale` | `1` | Feature size of generated scenes; higher is finer. Use about 1.8 on phones, where the field is tall. (4.12) |
38
+ | `clear` | `false` | Keeps the field quiet around content so text stays readable: an element, `{ element, padding, feather, shape }` (followed through layout changes), or a zone in field fractions. (4.12) |
36
39
  | `charset` | `' .,:-=+*#%@'` | Ordered from empty to dense. Graphemes, so emoji, braille and block shading each take one cell. Up to 256. |
37
40
  | `cellSize`, `cellAspect` | `12`, `1` | Cell height in CSS px; width ÷ height. Monospaced ramps look best near `0.6`. Cells are whole device pixels, and glyphs are sampled texel for texel. |
38
41
  | `font`, `fontWeight`, `glyphScale` | monospace, `500`, `0.8` | Any loaded CSS font. The atlas is redrawn when the font finishes loading. |
@@ -56,6 +59,26 @@ Size the canvas with CSS (for example `position:absolute; inset:0; width:100%; h
56
59
 
57
60
  `update(options)` merges and rebuilds only what changed (the atlas for type changes, the simulation for resolution changes). `setSource(source)` swaps media. `pointer(x, y)` moves the wake in CSS pixels relative to the canvas (`pointer(null)` lifts it), which is useful for an intro stroke. `redraw()` draws immediately, so you can copy the canvas with `drawImage` in the same task, for example to cross-fade between looks.
58
61
 
62
+ ## Halftone for interfaces (4.12)
63
+
64
+ Product pages, docs, pricing and SaaS heroes want a background that is calm, works in light and dark themes, and never fights the copy. Use dots, the drift scene, a clear zone around the content, and `pulse()` for interface events:
65
+
66
+ ```ts
67
+ const field = mountGlyphField(heroCanvas, {
68
+ mark: 'dot', scene: 'drift', cellSize: 14, dotScale: 0.64,
69
+ color: 'ink', ink: tokens.textMuted, background: 'transparent',
70
+ clear: { element: heroCopy, padding: 40, feather: 0.18 },
71
+ hover: 'lantern',
72
+ });
73
+ saveButton.addEventListener('click', () => field.pulse({ element: saveButton }));
74
+ ```
75
+
76
+ - Ink: the muted text token, not the accent. On light grounds a mid grey such as `#9a988f`; on dark about `#5f5e58`.
77
+ - Clear zone: always set one when text sits over the field. Measure contrast at the busiest frame anyway.
78
+ - Pulse: one ring per meaningful event (saved, sent, connected), not on every click. It is skipped under reduced motion.
79
+ - `pulse({ x, y })` takes CSS pixels relative to the canvas; `pulse({ element })` starts at the element's centre; no argument starts at the centre.
80
+
81
+
59
82
  ## Living or still
60
83
 
61
84
  A photo with `drift: 0`, no video and a pointer that has left draws once and stops. Add `drift` (0.15–0.35) to let it breathe, use a video, or use a generated `scene` for continuous motion. Choose by the user's words and the context; [design-matching.md](design-matching.md#living-or-still) has the rules. Reduced motion stops drift and generated scenes; Lantern follows instantly and stops flickering.