asciify-engine 1.0.117 → 1.1.0
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.
- package/README.md +35 -1
- package/dist/backgrounds.cjs +1 -0
- package/dist/backgrounds.d.cts +401 -0
- package/dist/backgrounds.d.ts +401 -0
- package/dist/backgrounds.js +1 -0
- package/dist/core.cjs +1 -0
- package/dist/core.d.cts +1265 -0
- package/dist/core.d.ts +1265 -0
- package/dist/core.js +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -1668
- package/dist/index.d.ts +2 -1668
- package/dist/index.js +1 -1
- package/examples/media-background.ts +22 -0
- package/package.json +26 -3
- package/skills/asciify-engine/SKILL.md +76 -749
- package/skills/asciify-engine/agents/openai.yaml +2 -2
- package/skills/asciify-engine/examples/layered-hero.css +30 -0
- package/skills/asciify-engine/examples/layered-hero.html +31 -0
- package/skills/asciify-engine/examples/layered-hero.js +78 -0
- package/skills/asciify-engine/references/layered-hero.md +45 -0
- package/skills/asciify-engine/references/media-api.md +109 -0
- package/skills/asciify-engine/references/studio-effects.md +51 -0
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -1,801 +1,128 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: asciify-engine
|
|
3
|
-
description:
|
|
3
|
+
description: Build and tune browser ASCII images, video, GIFs, text, and interactive heroes with asciify-engine. Use for media conversion, character and color choices, hover integration, layered HTML typography, scroll-synced video, and rendering performance in apps using this package.
|
|
4
|
+
metadata:
|
|
5
|
+
tested-engine: "1.1.0"
|
|
6
|
+
updated: "2026-09-08"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
|
-
#
|
|
9
|
+
# Asciify Engine
|
|
7
10
|
|
|
8
|
-
Use
|
|
11
|
+
Use the published `asciify-engine` npm package for browser canvas rendering. Tested against **1.1.0**. Check the application's installed version and its public types before using newer options; a local checkout can contain unpublished changes.
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
- Agent entry: https://asciify.org/skill (redirects to this Markdown document).
|
|
14
|
+
- Playground: https://asciify.org/editor
|
|
15
|
+
- API documentation: https://asciify.org/docs/api
|
|
16
|
+
- Repository: https://github.com/ayangabryl/asciify-engine
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## When To Use
|
|
18
|
-
|
|
19
|
-
Use this skill when the user wants to:
|
|
20
|
-
|
|
21
|
-
- Convert images, videos, GIFs, webcam, or text into ASCII art.
|
|
22
|
-
- Add ASCII video/backgrounds to React, Next.js, Vue, Svelte, or vanilla JS.
|
|
23
|
-
- Build scroll-synced ASCII video with GSAP ScrollTrigger or native scroll.
|
|
24
|
-
- Improve ASCII media performance, FPS, detail, resolution, or hover behavior.
|
|
25
|
-
- Use chroma key, fullcolor, accent, matrix, grayscale, dense/braille charsets, or hover effects.
|
|
26
|
-
- Use low-level prepared/compact frame APIs.
|
|
27
|
-
- Record/export ASCII canvas output.
|
|
28
|
-
- Update docs, package usage, or skill instructions for `asciify-engine`.
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install asciify-engine
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
For existing apps, install the latest tested version:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npm install asciify-engine@1.0.115
|
|
18
|
+
```sh
|
|
19
|
+
npm install asciify-engine@1.1.0
|
|
40
20
|
```
|
|
41
21
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Prefer the simple APIs first:
|
|
45
|
-
|
|
46
|
-
- `asciify()` for static images/canvas/video elements.
|
|
47
|
-
- `asciifyVideo()` for live or scroll-synced video.
|
|
48
|
-
- `asciifyGif()` for animated GIF files.
|
|
49
|
-
- `asciiBackground()` for procedural ASCII backgrounds.
|
|
50
|
-
|
|
51
|
-
For high-performance media, the engine uses compact text-frame paths when possible:
|
|
52
|
-
|
|
53
|
-
- `imageToAsciiTextFrame()`
|
|
54
|
-
- `videoToAsciiTextFrames()`
|
|
55
|
-
- `gifToAsciiTextFrames()`
|
|
56
|
-
- `renderTextFrameToCanvas()`
|
|
22
|
+
Version 1.1.0 exports `asciify-engine`, `asciify-engine/core` for media without procedural generators, and `asciify-engine/backgrounds` for optional backgrounds. Root imports remain supported. GIF decoding loads `gifuct-js` when a GIF API is called. Site-internal studio modules are separate.
|
|
57
23
|
|
|
58
|
-
|
|
24
|
+
## Install the agent skill
|
|
59
25
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- `imageToAsciiFrame()`
|
|
63
|
-
- `videoToAsciiFrames()`
|
|
64
|
-
- `gifToAsciiFrames()`
|
|
65
|
-
- `renderFrameToCanvas()`
|
|
66
|
-
|
|
67
|
-
Use `options.sourceCrop` when the source media has empty edges or needs tighter framing. Percent values are normalized `0–1` by default. Prefer CSS-like insets for readable framing; side insets define the crop window directly, and `asciifyVideo` sizes from that crop aspect so it does not stretch:
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
options: {
|
|
71
|
-
sourceCrop: { top: 0.08, bottom: 0.22 },
|
|
72
|
-
}
|
|
26
|
+
```sh
|
|
27
|
+
npx skills add ayangabryl/asciify-engine --skill asciify-engine
|
|
73
28
|
```
|
|
74
29
|
|
|
75
|
-
|
|
30
|
+
This uses the Vercel Skills CLI to install the repository skill and its linked resources. Updating the npm dependency alone does not update an already installed skill. Use `npx skills update asciify-engine` to refresh it.
|
|
76
31
|
|
|
77
|
-
|
|
78
|
-
options: {
|
|
79
|
-
sourceCrop: { left: 0.1, right: 0.1 },
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Use any side together:
|
|
32
|
+
## Choose the integration
|
|
84
33
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
34
|
+
- Static image: `asciify(source, canvas, config)` returns `Promise<() => void>`. Call the cleanup on unmount, including for a still image.
|
|
35
|
+
- Video: `asciifyVideo(source, canvas, config)` returns `Promise<() => void>`. Call that function on unmount. Use `fitTo` and `objectFit: 'cover'` for full-bleed heroes; `contain` for a whole-subject preview.
|
|
36
|
+
- GIF: `asciifyGif(source, canvas, config)` returns a cleanup function asynchronously.
|
|
37
|
+
- Procedural background: `asciiBackground(host, config)` returns an object with **`destroy()`**, not a stop function. Media conversion does not require adding a procedural background.
|
|
38
|
+
- Dense custom rendering: use `imageToAsciiTextFrame` and `renderTextFrameToCanvas`; keep the same options when converting and rendering. Use object frames when per-cell mutation is required.
|
|
90
39
|
|
|
91
|
-
For
|
|
40
|
+
For a hero with HTML layered through the ASCII, read [references/layered-hero.md](references/layered-hero.md) and use the accompanying [HTML](examples/layered-hero.html), [CSS](examples/layered-hero.css), and [JavaScript](examples/layered-hero.js). These are ordinary Vite/bundler inputs, not another npm dependency. Supply your own media.
|
|
92
41
|
|
|
93
|
-
|
|
42
|
+
For crop, scroll, React lifecycle, and low-level API details, read [references/media-api.md](references/media-api.md).
|
|
94
43
|
|
|
95
|
-
|
|
96
|
-
If the canvas is full width but the visible keyed subject still feels short, raise `chromaKeyTrimLuminanceThreshold` slightly, usually `6–16`, so invisible edge noise is not counted as foreground.
|
|
44
|
+
## Start with a readable source
|
|
97
45
|
|
|
98
|
-
|
|
46
|
+
Use ordinary images or footage, then convert them with Asciify. Do not ask an image/video generator to pre-render ASCII. A dark subject with thin highlights tends to become an outline; changing to full color cannot recover missing midtones. Prefer recognizable subjects, broad illuminated surfaces, controlled highlights, and stable framing.
|
|
99
47
|
|
|
100
|
-
|
|
101
|
-
options: {
|
|
102
|
-
chromaKey: true,
|
|
103
|
-
sourceCrop: { top: 0.08, bottom: 0.16 },
|
|
104
|
-
chromaKeyTrimMode: 'frame',
|
|
105
|
-
chromaKeyTrimPadding: 0,
|
|
106
|
-
}
|
|
107
|
-
```
|
|
48
|
+
Choose color intentionally:
|
|
108
49
|
|
|
109
|
-
|
|
50
|
+
- `fullcolor`: preserve source colors; do not grayscale source pixels first.
|
|
51
|
+
- `grayscale`: gray characters.
|
|
52
|
+
- `accent`: a single brand color via `accentColor`.
|
|
53
|
+
- `matrix`: green treatment.
|
|
110
54
|
|
|
111
|
-
|
|
55
|
+
Start around `fontSize: 7`, `fps: 24` or `30`, and `maxRenderDimension: 960`. These are a starting budget, not an FPS guarantee. Increase detail only after checking the actual viewport and target hardware. Use `normalize: true` for flat sources when helpful; compare it against `false` on already graded video because frame-by-frame normalization may change the look.
|
|
112
56
|
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
objectFit: 'contain',
|
|
117
|
-
objectPosition: 'center bottom',
|
|
118
|
-
width: '100vw',
|
|
119
|
-
height: '100%',
|
|
120
|
-
bleed: { x: '2vw' },
|
|
121
|
-
options: {
|
|
122
|
-
sourceCrop: { top: 0.08, bottom: 0.14 },
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Mental split:
|
|
128
|
-
|
|
129
|
-
- `sourceCrop` chooses the source window before ASCII conversion.
|
|
130
|
-
- CSS-like insets change the crop aspect naturally; the engine keeps ASCII proportions intact.
|
|
131
|
-
- `objectFit`, `objectPosition`, `scale`, `width`, `height`, and `bleed` place the rendered canvas in the page.
|
|
132
|
-
- Use `objectFit: 'cover'` for full-width/full-bleed heroes and backgrounds.
|
|
133
|
-
- Use `objectFit: 'contain'` for previews where the whole source should remain visible.
|
|
134
|
-
- Use `bleed: { x: '2vw' }` for edge-tight ASCII heroes where the source is correct but glyph side bearings or cell quantization leave a thin visual edge gap. This is preferable to app CSS hacks like `width: 104vw`.
|
|
135
|
-
- Use `scale` only when you intentionally want the whole ASCII canvas visually larger.
|
|
136
|
-
|
|
137
|
-
## Visual Target
|
|
138
|
-
|
|
139
|
-
Good ASCII media should feel intentional, not like a broken video filter.
|
|
140
|
-
|
|
141
|
-
- The subject silhouette is readable at first glance.
|
|
142
|
-
- Character density reveals form, light, and motion without turning into noise.
|
|
143
|
-
- The canvas respects the media aspect ratio and fills the intended container.
|
|
144
|
-
- Accent/fullcolor choices support the page design instead of shouting over it.
|
|
145
|
-
- Text is crisp, not browser-blurred, stretched, or visibly low resolution.
|
|
146
|
-
- Motion updates feel continuous; if FPS drops, reduce work before adding effects.
|
|
147
|
-
|
|
148
|
-
## Decision Playbooks
|
|
149
|
-
|
|
150
|
-
### User Wants More Detail
|
|
151
|
-
|
|
152
|
-
Do not only reduce `fontSize`. Use this ladder:
|
|
153
|
-
|
|
154
|
-
1. Confirm the canvas/container is actually large enough and not CSS-stretched from a tiny backing buffer.
|
|
155
|
-
2. Use `fitTo` for videos so the engine owns canvas sizing.
|
|
156
|
-
3. Use `CHARSETS.dense` for normal ASCII detail.
|
|
157
|
-
4. Enable `normalize: true` for muted or low-contrast sources.
|
|
158
|
-
5. Raise `maxRenderDimension` one step: `960 -> 1280 -> 1600 -> 2048`.
|
|
159
|
-
6. Then lower `fontSize`: `8 -> 6 -> 5 -> 4`.
|
|
160
|
-
7. Try `colorMode: 'accent'` before `fullcolor` if the design can be monochrome.
|
|
161
|
-
8. Use `CHARSETS.braille` only when ultra-detail matters and the style can handle the texture.
|
|
162
|
-
|
|
163
|
-
Stop when the subject reads clearly. More cells after that often make the image noisier, not better.
|
|
164
|
-
|
|
165
|
-
### User Wants Smoother FPS
|
|
166
|
-
|
|
167
|
-
Reduce hot-path work in this order:
|
|
168
|
-
|
|
169
|
-
1. Keep `animationStyle: 'none'` and `hoverStrength: 0`.
|
|
170
|
-
2. Use compact text-frame-compatible settings: `renderMode: 'ascii'`, no `charsetFrames`.
|
|
171
|
-
3. Prefer `accent`, `matrix`, or `grayscale`; keep `fullcolor` only when color matters.
|
|
172
|
-
4. Lower `maxRenderDimension`: `2048 -> 1600 -> 1280 -> 960`.
|
|
173
|
-
5. Raise `fontSize`: `4 -> 5 -> 6 -> 8`.
|
|
174
|
-
6. Lower `fps`: `60 -> 30 -> 24`.
|
|
175
|
-
7. Avoid `dots`, per-cell hover, and animated charsets on dense video.
|
|
176
|
-
|
|
177
|
-
If FPS is still poor, inspect whether the app is resizing the canvas every frame or remounting the component.
|
|
178
|
-
|
|
179
|
-
### User Wants A Premium Hero
|
|
180
|
-
|
|
181
|
-
Recommended starting point:
|
|
182
|
-
|
|
183
|
-
```ts
|
|
184
|
-
{
|
|
57
|
+
```js
|
|
58
|
+
import { asciifyVideo } from 'asciify-engine';
|
|
59
|
+
const stop = await asciifyVideo('/hero.mp4', canvas, {
|
|
185
60
|
fitTo: hero,
|
|
186
|
-
objectFit: '
|
|
187
|
-
objectPosition: 'center
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
fontSize: 5,
|
|
192
|
-
fps: 60,
|
|
193
|
-
maxRenderDimension: 1280,
|
|
194
|
-
maxCachedFrames: 96,
|
|
195
|
-
artStyle: 'classic',
|
|
61
|
+
objectFit: 'cover',
|
|
62
|
+
objectPosition: 'center',
|
|
63
|
+
fontSize: 7,
|
|
64
|
+
fps: 24,
|
|
65
|
+
maxRenderDimension: 960,
|
|
196
66
|
options: {
|
|
197
|
-
charset:
|
|
198
|
-
colorMode: 'accent',
|
|
199
|
-
accentColor: '#e8d7b7',
|
|
200
|
-
normalize: true,
|
|
201
|
-
sourceCrop: { top: 0.08, bottom: 0.16 },
|
|
202
|
-
animationStyle: 'none',
|
|
203
|
-
hoverStrength: 0,
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
Design rules:
|
|
209
|
-
|
|
210
|
-
- Use one restrained accent color pulled from the brand/page palette.
|
|
211
|
-
- Put ASCII behind or below the core CTA, not directly under tiny text.
|
|
212
|
-
- Use masks or fades at edges when the ASCII meets page content.
|
|
213
|
-
- Keep the hero background quiet enough that the headline wins.
|
|
214
|
-
- Use scroll scrub only when it tells a story; do not scrub decorative noise.
|
|
215
|
-
|
|
216
|
-
### User Wants Fullcolor
|
|
217
|
-
|
|
218
|
-
Use fullcolor when color carries product meaning, artwork, identity, or footage mood.
|
|
219
|
-
|
|
220
|
-
Start with:
|
|
221
|
-
|
|
222
|
-
```ts
|
|
223
|
-
{
|
|
224
|
-
fontSize: 6,
|
|
225
|
-
fps: 30,
|
|
226
|
-
maxRenderDimension: 1280,
|
|
227
|
-
artStyle: 'art',
|
|
228
|
-
options: {
|
|
229
|
-
charset: CHARSETS.dense,
|
|
67
|
+
charset: ' .:-=+*#%@',
|
|
230
68
|
colorMode: 'fullcolor',
|
|
231
|
-
normalize:
|
|
232
|
-
sourceCrop: { top: 0.08, bottom: 0.16 },
|
|
69
|
+
normalize: false,
|
|
233
70
|
animationStyle: 'none',
|
|
234
71
|
hoverStrength: 0,
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
If it is slow, first lower `maxRenderDimension` or raise `fontSize`. Do not jump straight to `fontSize: 3`.
|
|
240
|
-
|
|
241
|
-
### User Wants Hover Interaction
|
|
242
|
-
|
|
243
|
-
Hover is per-cell work. Keep it deliberate:
|
|
244
|
-
|
|
245
|
-
- Use `fontSize >= 8` for large canvases.
|
|
246
|
-
- Use smaller framed demos rather than full-screen 4px ASCII.
|
|
247
|
-
- Start with `HOVER_PRESETS.subtle` or `hoverStrength: 0.2`.
|
|
248
|
-
- Avoid hover on scroll-synced video unless the canvas is small.
|
|
249
|
-
- Prefer hover for static images, generated text backgrounds, or product demos.
|
|
250
|
-
|
|
251
|
-
### User Says It Is Blurry
|
|
252
|
-
|
|
253
|
-
Check in this order:
|
|
254
|
-
|
|
255
|
-
1. Is the canvas CSS size different from its backing `width`/`height`?
|
|
256
|
-
2. For video, is `fitTo` provided?
|
|
257
|
-
3. Is the source itself low resolution?
|
|
258
|
-
4. Is `maxRenderDimension` too low for the displayed size?
|
|
259
|
-
5. Is CSS applying `filter`, `transform: scale`, or opacity compositing that softens text?
|
|
260
|
-
6. For tiny font ASCII, verify the design accepts raster-like pixel detail.
|
|
261
|
-
|
|
262
|
-
### User Says It Is Blank
|
|
263
|
-
|
|
264
|
-
Check:
|
|
265
|
-
|
|
266
|
-
1. Source loaded and video has metadata.
|
|
267
|
-
2. Canvas has nonzero width/height.
|
|
268
|
-
3. Video is not `display: none`.
|
|
269
|
-
4. `chromaKey` is not removing the subject.
|
|
270
|
-
5. `invert` and page background are not making characters invisible.
|
|
271
|
-
6. For async React use, cleanup did not run before `asciifyVideo()` resolved.
|
|
272
|
-
|
|
273
|
-
### User Says It Is Too Large Or Overflows
|
|
274
|
-
|
|
275
|
-
Use layout fixes before quality fixes:
|
|
276
|
-
|
|
277
|
-
- Wrap canvas in a positioned container.
|
|
278
|
-
- Set canvas CSS to `position:absolute; inset:0; width:100%; height:100%`.
|
|
279
|
-
- Use `fitTo: container`.
|
|
280
|
-
- Keep the parent aspect ratio or explicit height stable.
|
|
281
|
-
- Avoid manually setting `canvas.width = window.innerWidth` in React render.
|
|
282
|
-
|
|
283
|
-
### User Wants To Remove Empty Space In The Media
|
|
284
|
-
|
|
285
|
-
Prefer source cropping over layout hacks when the video/image itself has dead space:
|
|
286
|
-
|
|
287
|
-
```ts
|
|
288
|
-
await asciifyVideo(video, canvas, {
|
|
289
|
-
fitTo: hero,
|
|
290
|
-
options: {
|
|
291
|
-
chromaKey: true,
|
|
292
|
-
sourceCrop: { top: 0.08, bottom: 0.22 },
|
|
293
72
|
},
|
|
294
73
|
});
|
|
74
|
+
// On unmount: stop();
|
|
295
75
|
```
|
|
296
76
|
|
|
297
|
-
|
|
298
|
-
- Default unit is `'percent'`; use values from `0` to `1`.
|
|
299
|
-
- Use `top`, `right`, `bottom`, and `left` for CSS-like side crops.
|
|
300
|
-
- Use `{ unit: 'pixel', x, y, width, height }` for exact media-pixel crops.
|
|
301
|
-
- Keep `preserveAspect` enabled unless you intentionally want an exact source window that can stretch.
|
|
302
|
-
- For hero videos, crop the source first, then use small layout overlap only if the next section needs to tuck closer.
|
|
303
|
-
|
|
304
|
-
### Scroll-Scrub Performance Model
|
|
305
|
-
|
|
306
|
-
In `1.0.93+`, the fast text-frame scrub path uses a Pretext-inspired split:
|
|
77
|
+
## Custom letters
|
|
307
78
|
|
|
308
|
-
|
|
309
|
-
- Render compact row strings instead of object-per-cell frames.
|
|
310
|
-
- Diff transparent rows and only redraw rows whose text changed.
|
|
311
|
-
- Prefer `fastSeek()` when the browser supports it.
|
|
312
|
-
- Prefetch nearby frames around the current target so scrolling back and forth has fewer misses.
|
|
79
|
+
`options.charset` is the density ramp. `customText` repeats a string and is a different feature. To incorporate a brand's letters while retaining shading symbols, build a ramp such as:
|
|
313
80
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
{
|
|
318
|
-
renderMode: 'ascii',
|
|
319
|
-
animationStyle: 'none',
|
|
320
|
-
hoverStrength: 0,
|
|
321
|
-
colorMode: 'accent', // or grayscale/matrix
|
|
322
|
-
}
|
|
81
|
+
```js
|
|
82
|
+
const letters = [...new Set('ASCIIFY'.toUpperCase().replace(/[^A-Z]/g, ''))].join('');
|
|
83
|
+
const charset = ` .:-=+${letters}#%@`;
|
|
323
84
|
```
|
|
324
85
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
### Dark Premium Landing Page
|
|
328
|
-
|
|
329
|
-
- Use `#121212` or near-black page background.
|
|
330
|
-
- Prefer `accent` over `fullcolor` unless the footage itself is beautiful.
|
|
331
|
-
- Use warm off-white or brand accent, not neon by default.
|
|
332
|
-
- Pair ASCII with framed layout, thin borders, or quiet masks.
|
|
333
|
-
- Keep copy short; ASCII should carry some of the storytelling.
|
|
86
|
+
Preview it: letter glyph densities differ, so arbitrary words are not automatically an evenly ordered ramp. Keep the leading space and the light/dense symbols. Use `CHARSETS.standard`, `dense`, `blocks`, or `braille` when they better suit the subject.
|
|
334
87
|
|
|
335
|
-
|
|
88
|
+
## Engine effects versus studio effects
|
|
336
89
|
|
|
337
|
-
|
|
338
|
-
- Use `CHARSETS.dense`, `lines`, `box`, or `geometric`.
|
|
339
|
-
- Compose with visible grid lines, clipped containers, and measured spacing.
|
|
340
|
-
- Avoid playful emoji/katakana unless the brand asks for it.
|
|
90
|
+
The public npm `HoverEffect` IDs in 1.1.0 are `spotlight`, `magnify`, `repel`, `glow`, `colorShift`, `attract`, `shatter`, `trail`, and `glitchText`. Those remain valid APIs, but they are **not identical to the current website's enhanced interactions**.
|
|
341
91
|
|
|
342
|
-
|
|
92
|
+
The website offers **Trail, Water, Contour, Dissolve, Silk, Vortex, and Off** through an optional studio surface module. Its Living Print, Slow Current, Reveal & Reform, and fine-dither treatments are also site features; do not invent npm options from their display names.
|
|
343
93
|
|
|
344
|
-
-
|
|
345
|
-
- Use slower video, stills, or subtle scroll reveal.
|
|
346
|
-
- Keep `fontSize: 5-8`; avoid over-dense unreadable texture.
|
|
347
|
-
- Use ASCII as proof/atmosphere around work, not as a gimmick.
|
|
94
|
+
To reproduce those interactions, read [references/studio-effects.md](references/studio-effects.md). The module is downloadable application code. Keep engine `hoverStrength: 0` and `animationStyle: 'none'` when using it, to avoid applying two effects. Trail is the site's default. Prefer a stationary-grid effect such as Trail or Dissolve when the user wants a wake without spatial displacement.
|
|
348
95
|
|
|
349
|
-
|
|
96
|
+
For built-in hover alone, use a supported `options.hoverEffect` and a restrained nonzero `hoverStrength`; validate its behavior instead of promising that it matches the website.
|
|
350
97
|
|
|
351
|
-
|
|
352
|
-
- Surface live `cols x rows`, FPS, and current source dimensions.
|
|
353
|
-
- Include presets: `Smooth`, `Detailed`, `Fullcolor`, `Interactive`.
|
|
354
|
-
- When changing presets, explain the performance tradeoff in the UI.
|
|
98
|
+
## Text layering
|
|
355
99
|
|
|
356
|
-
|
|
100
|
+
Use real HTML for the headline, description, and links. The engine draws artwork; CSS controls which HTML sits in front of it.
|
|
357
101
|
|
|
358
|
-
|
|
359
|
-
- FPS is stable for 5-10 seconds, not just on first load.
|
|
360
|
-
- The canvas does not resize every frame.
|
|
361
|
-
- Text/CTA remains readable over or near the ASCII.
|
|
362
|
-
- Mobile uses a less expensive preset than desktop when needed.
|
|
363
|
-
- Reduced-motion users still get a static or slower frame.
|
|
364
|
-
- Cleanup runs on unmount and cancels video/background loops.
|
|
102
|
+
For our cover relationship, use a single isolated hero stacking context:
|
|
365
103
|
|
|
366
|
-
|
|
104
|
+
1. Headline at `z-index: 0`.
|
|
105
|
+
2. Transparent ASCII canvas/stage at `z-index: 1`.
|
|
106
|
+
3. Description, CTA, and motion controls at `z-index: 2` or above.
|
|
367
107
|
|
|
368
|
-
|
|
108
|
+
Keep these as sibling layers. A transformed or isolated content wrapper can trap all its descendants below the canvas. Set decorative artwork to `pointer-events: none`; attach optional hover input to the positioned hero host. Keep controls clickable, focusable, and visually unobscured. Leave canvas background transparent; an opaque canvas or stage hides the headline beneath it.
|
|
369
109
|
|
|
370
|
-
|
|
371
|
-
import { asciify, CHARSETS } from 'asciify-engine';
|
|
372
|
-
|
|
373
|
-
await asciify('/photo.jpg', canvas, {
|
|
374
|
-
fontSize: 6,
|
|
375
|
-
artStyle: 'art',
|
|
376
|
-
options: {
|
|
377
|
-
charset: CHARSETS.dense,
|
|
378
|
-
colorMode: 'fullcolor',
|
|
379
|
-
normalize: true,
|
|
380
|
-
},
|
|
381
|
-
});
|
|
382
|
-
```
|
|
110
|
+
Choose the more conventional arrangement—artwork behind all text—when it improves readability. The layered example explains both arrangements without imposing the Asciify homepage's branding or layout on another project.
|
|
383
111
|
|
|
384
|
-
|
|
112
|
+
## Performance and lifecycle
|
|
385
113
|
|
|
386
|
-
|
|
387
|
-
|
|
114
|
+
- Reduce processing dimensions and cell count before dropping source playback FPS. Do not default to 60 fps on a 24 fps video.
|
|
115
|
+
- Start video at 24–30 fps with a 720–960px processing cap. More processing pixels do not create detail absent from the source. Version 1.1.0 includes the renderer fixes previously applied by the website; it does not include the optional studio surface module.
|
|
116
|
+
- Keep stable canvas dimensions; resize on layout changes, not on every animation frame.
|
|
117
|
+
- Avoid remounting the renderer on pointer movement or each React render.
|
|
118
|
+
- Pause media offscreen and when the document is hidden. Reduced-motion users should get a still; do not merely hide a playing video with CSS.
|
|
119
|
+
- Guard asynchronous setup: if a component unmounts before an API resolves, immediately call its returned cleanup. Handle loading failures without removing the HTML content or CTA.
|
|
120
|
+
- Compress media at a resolution appropriate to ASCII sampling, remove unused audio, use fast-start MP4, and provide a small poster. Immutable caching requires a content-hashed URL; keep this skill's URL revalidatable.
|
|
121
|
+
- Fine dithering can add texture but can shimmer on moving footage. Compare a still and a loop, and offer a non-dithered rendering.
|
|
122
|
+
- YouTube page URLs and iframe players are not direct canvas video sources. Use permitted direct media files with suitable CORS; see https://asciify.org/docs/youtube.
|
|
388
123
|
|
|
389
|
-
|
|
390
|
-
fitTo: container,
|
|
391
|
-
fontSize: 6,
|
|
392
|
-
fps: 60,
|
|
393
|
-
maxRenderDimension: 1280,
|
|
394
|
-
artStyle: 'classic',
|
|
395
|
-
options: {
|
|
396
|
-
charset: CHARSETS.dense,
|
|
397
|
-
colorMode: 'accent',
|
|
398
|
-
accentColor: '#e8d7b7',
|
|
399
|
-
normalize: true,
|
|
400
|
-
},
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
// cleanup
|
|
404
|
-
stop();
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### GIF
|
|
408
|
-
|
|
409
|
-
```ts
|
|
410
|
-
import { asciifyGif } from 'asciify-engine';
|
|
411
|
-
|
|
412
|
-
const stop = await asciifyGif('/loop.gif', canvas, {
|
|
413
|
-
fontSize: 8,
|
|
414
|
-
artStyle: 'letters',
|
|
415
|
-
options: { colorMode: 'fullcolor' },
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
stop();
|
|
419
|
-
```
|
|
124
|
+
## Verify before handing off
|
|
420
125
|
|
|
421
|
-
|
|
126
|
+
Check the actual implementation: readable subject and text, no stretching or unintended empty margins, working pointer and keyboard controls, mobile crop, reduced motion, autoplay failure, and cleanup after navigation. Observe several seconds of motion and an entire loop boundary. State the measured device/settings if reporting FPS; screenshots and recordings alone do not establish performance.
|
|
422
127
|
|
|
423
|
-
`
|
|
424
|
-
|
|
425
|
-
### GSAP ScrollTrigger
|
|
426
|
-
|
|
427
|
-
```ts
|
|
428
|
-
import gsap from 'gsap';
|
|
429
|
-
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
430
|
-
import { asciifyVideo, CHARSETS } from 'asciify-engine';
|
|
431
|
-
|
|
432
|
-
const stop = await asciifyVideo('/hero.mp4', canvas, {
|
|
433
|
-
fitTo: wrapper,
|
|
434
|
-
fontSize: 4,
|
|
435
|
-
fps: 60,
|
|
436
|
-
maxRenderDimension: 1280,
|
|
437
|
-
trim: { start: 2.2, end: 6.65 },
|
|
438
|
-
scroll: {
|
|
439
|
-
gsap,
|
|
440
|
-
ScrollTrigger,
|
|
441
|
-
trigger: wrapper,
|
|
442
|
-
start: 'top 88%',
|
|
443
|
-
end: 'bottom 18%',
|
|
444
|
-
scrub: 0.45,
|
|
445
|
-
speed: 1.35,
|
|
446
|
-
from: 2.2,
|
|
447
|
-
to: 6.65,
|
|
448
|
-
},
|
|
449
|
-
options: {
|
|
450
|
-
charset: CHARSETS.dense,
|
|
451
|
-
colorMode: 'accent',
|
|
452
|
-
accentColor: '#e8d7b7',
|
|
453
|
-
normalize: true,
|
|
454
|
-
chromaKey: true,
|
|
455
|
-
chromaKeyTolerance: 84,
|
|
456
|
-
},
|
|
457
|
-
});
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
### Native Scroll Scrub
|
|
461
|
-
|
|
462
|
-
```ts
|
|
463
|
-
const stop = await asciifyVideo('/hero.mp4', canvas, {
|
|
464
|
-
fitTo: wrapper,
|
|
465
|
-
fontSize: 6,
|
|
466
|
-
scroll: {
|
|
467
|
-
trigger: wrapper,
|
|
468
|
-
from: 0,
|
|
469
|
-
to: 5,
|
|
470
|
-
},
|
|
471
|
-
});
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Scroll Best Practices
|
|
475
|
-
|
|
476
|
-
- Use `scroll` for time-to-scroll mapping, not custom `video.currentTime` loops.
|
|
477
|
-
- Pass the same `from`/`to` as `trim.start`/`trim.end` when scrubbing a clipped range.
|
|
478
|
-
- Use `scroll.speed` for faster or slower scrub pacing. `speed: 2` reaches the end in half the scroll distance; `speed: 0.5` takes twice the distance.
|
|
479
|
-
- Use `fps: 30-60`; choose `60` for smooth short hero clips, `24-30` for heavy fullcolor.
|
|
480
|
-
- Use `maxRenderDimension: 960-1280` for large full-width hero videos. Use `2048` only when truly needed.
|
|
481
|
-
- Use `fontSize: 4-6` for detailed hero ASCII; below `4px` is expensive and should use compact text-frame paths only.
|
|
482
|
-
- Avoid hover effects on dense scroll video. Hover is per-cell work.
|
|
483
|
-
- Never set the backing video to `display: none`; the API keeps URL-created videos decode-safe automatically.
|
|
484
|
-
|
|
485
|
-
## Performance Guide
|
|
486
|
-
|
|
487
|
-
### Fastest Media Settings
|
|
488
|
-
|
|
489
|
-
For smooth high-density video:
|
|
490
|
-
|
|
491
|
-
```ts
|
|
492
|
-
{
|
|
493
|
-
fontSize: 5,
|
|
494
|
-
fps: 60,
|
|
495
|
-
maxRenderDimension: 1280,
|
|
496
|
-
artStyle: 'classic',
|
|
497
|
-
options: {
|
|
498
|
-
charset: CHARSETS.dense,
|
|
499
|
-
colorMode: 'accent',
|
|
500
|
-
animationStyle: 'none',
|
|
501
|
-
hoverStrength: 0,
|
|
502
|
-
normalize: true,
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
### Fullcolor Settings
|
|
508
|
-
|
|
509
|
-
Fullcolor is supported by the compact text-frame path in `1.0.91+`.
|
|
510
|
-
|
|
511
|
-
```ts
|
|
512
|
-
{
|
|
513
|
-
fontSize: 6,
|
|
514
|
-
fps: 30,
|
|
515
|
-
maxRenderDimension: 1280,
|
|
516
|
-
artStyle: 'art',
|
|
517
|
-
options: {
|
|
518
|
-
charset: CHARSETS.dense,
|
|
519
|
-
colorMode: 'fullcolor',
|
|
520
|
-
animationStyle: 'none',
|
|
521
|
-
hoverStrength: 0,
|
|
522
|
-
normalize: true,
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
Use fullcolor when the source color is important. Use `accent` when you want the highest FPS and a more designed monochrome look.
|
|
528
|
-
|
|
529
|
-
### Detail Tuning
|
|
530
|
-
|
|
531
|
-
- `fontSize`: main detail/performance knob. Smaller means more cells.
|
|
532
|
-
- `maxRenderDimension`: caps media processing resolution before ASCII conversion.
|
|
533
|
-
- `CHARSETS.dense`: best general image/video ramp.
|
|
534
|
-
- `CHARSETS.braille`: very high visual resolution but can be visually noisy and heavier.
|
|
535
|
-
- `normalize: true`: improves contrast/detail for muted media.
|
|
536
|
-
- `ditherStrength: 0-0.25`: adds texture but costs more and can shimmer in video.
|
|
537
|
-
- `chromaKey`: useful for green/blue-screen subjects over page backgrounds.
|
|
538
|
-
|
|
539
|
-
### Expensive Features
|
|
540
|
-
|
|
541
|
-
These are intentionally richer and can reduce FPS on dense canvases:
|
|
542
|
-
|
|
543
|
-
- `renderMode: 'dots'`
|
|
544
|
-
- `hoverStrength > 0`
|
|
545
|
-
- `animationStyle !== 'none'`
|
|
546
|
-
- `charsetFrames`
|
|
547
|
-
- tiny `fontSize` with `fullcolor`
|
|
548
|
-
- very high `maxRenderDimension`
|
|
549
|
-
|
|
550
|
-
For interactive hover demos, use `fontSize >= 8` or smaller canvases.
|
|
551
|
-
|
|
552
|
-
## Low-Level APIs
|
|
553
|
-
|
|
554
|
-
### Compact Text Frames
|
|
555
|
-
|
|
556
|
-
Use for dense static images, GIFs, videos, and fullcolor media where you do not need per-cell mutation.
|
|
557
|
-
|
|
558
|
-
```ts
|
|
559
|
-
import {
|
|
560
|
-
imageToAsciiTextFrame,
|
|
561
|
-
renderTextFrameToCanvas,
|
|
562
|
-
DEFAULT_OPTIONS,
|
|
563
|
-
} from 'asciify-engine';
|
|
564
|
-
|
|
565
|
-
const frame = imageToAsciiTextFrame(img, {
|
|
566
|
-
...DEFAULT_OPTIONS,
|
|
567
|
-
fontSize: 6,
|
|
568
|
-
colorMode: 'fullcolor',
|
|
569
|
-
}, 1280, 720);
|
|
570
|
-
|
|
571
|
-
renderTextFrameToCanvas(ctx, frame, DEFAULT_OPTIONS, 1280, 720);
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
Available compact APIs:
|
|
575
|
-
|
|
576
|
-
```ts
|
|
577
|
-
imageToAsciiTextFrame(source, options, width?, height?) -> AsciiTextFrame
|
|
578
|
-
videoToAsciiTextFrames(video, options, width, height, fps?, maxSec?, onProgress?, startTime?)
|
|
579
|
-
gifToAsciiTextFrames(buffer, options, width, height, onProgress?)
|
|
580
|
-
renderTextFrameToCanvas(ctx, textFrame, options, width, height)
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
`AsciiTextFrame` contains:
|
|
584
|
-
|
|
585
|
-
```ts
|
|
586
|
-
type AsciiTextFrame = {
|
|
587
|
-
rows: string[];
|
|
588
|
-
cols: number;
|
|
589
|
-
rowCount: number;
|
|
590
|
-
colors?: Uint8ClampedArray; // present for fullcolor compact frames
|
|
591
|
-
}
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### Legacy Object Frames
|
|
595
|
-
|
|
596
|
-
Use when you need cell objects, hover transforms, dots rendering, or compatibility:
|
|
597
|
-
|
|
598
|
-
```ts
|
|
599
|
-
imageToAsciiFrame(source, options, width?, height?) -> { frame, cols, rows }
|
|
600
|
-
videoToAsciiFrames(video, options, width, height, fps?, maxSec?, onProgress?, startTime?)
|
|
601
|
-
gifToAsciiFrames(buffer, options, width, height, onProgress?)
|
|
602
|
-
renderFrameToCanvas(ctx, frame, options, width, height, time?, mousePos?)
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
### Cache Management
|
|
606
|
-
|
|
607
|
-
Long-lived editors/playgrounds that cycle many charsets or fonts can clear shared lookup caches:
|
|
608
|
-
|
|
609
|
-
```ts
|
|
610
|
-
import { clearAsciifyCaches } from 'asciify-engine';
|
|
611
|
-
|
|
612
|
-
clearAsciifyCaches();
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
## React / Next.js Pattern
|
|
616
|
-
|
|
617
|
-
```tsx
|
|
618
|
-
'use client';
|
|
619
|
-
|
|
620
|
-
import { useEffect, useRef } from 'react';
|
|
621
|
-
import { asciifyVideo, CHARSETS } from 'asciify-engine';
|
|
622
|
-
|
|
623
|
-
export function AsciiHero() {
|
|
624
|
-
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
625
|
-
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
626
|
-
|
|
627
|
-
useEffect(() => {
|
|
628
|
-
const wrapper = wrapperRef.current;
|
|
629
|
-
const canvas = canvasRef.current;
|
|
630
|
-
if (!wrapper || !canvas) return;
|
|
631
|
-
|
|
632
|
-
let cleanup: (() => void) | undefined;
|
|
633
|
-
let alive = true;
|
|
634
|
-
|
|
635
|
-
asciifyVideo('/hero.mp4', canvas, {
|
|
636
|
-
fitTo: wrapper,
|
|
637
|
-
fontSize: 5,
|
|
638
|
-
fps: 60,
|
|
639
|
-
maxRenderDimension: 1280,
|
|
640
|
-
artStyle: 'classic',
|
|
641
|
-
options: {
|
|
642
|
-
charset: CHARSETS.dense,
|
|
643
|
-
colorMode: 'accent',
|
|
644
|
-
accentColor: '#e8d7b7',
|
|
645
|
-
normalize: true,
|
|
646
|
-
},
|
|
647
|
-
}).then(stop => {
|
|
648
|
-
if (alive) cleanup = stop;
|
|
649
|
-
else stop();
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
return () => {
|
|
653
|
-
alive = false;
|
|
654
|
-
cleanup?.();
|
|
655
|
-
};
|
|
656
|
-
}, []);
|
|
657
|
-
|
|
658
|
-
return (
|
|
659
|
-
<div ref={wrapperRef} style={{ position: 'relative', width: '100%', height: '100vh' }}>
|
|
660
|
-
<canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }} />
|
|
661
|
-
</div>
|
|
662
|
-
);
|
|
663
|
-
}
|
|
664
|
-
```
|
|
665
|
-
|
|
666
|
-
## Animated Backgrounds
|
|
667
|
-
|
|
668
|
-
```ts
|
|
669
|
-
import { asciiBackground } from 'asciify-engine';
|
|
670
|
-
|
|
671
|
-
const stop = asciiBackground('#hero-bg', {
|
|
672
|
-
type: 'aurora',
|
|
673
|
-
colorScheme: 'auto',
|
|
674
|
-
fontSize: 14,
|
|
675
|
-
speed: 0.8,
|
|
676
|
-
density: 0.55,
|
|
677
|
-
accentColor: '#d4ff00',
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
stop();
|
|
681
|
-
```
|
|
682
|
-
|
|
683
|
-
Available background types:
|
|
684
|
-
|
|
685
|
-
`wave`, `rain`, `stars`, `pulse`, `noise`, `grid`, `aurora`, `silk`, `void`, `morph`, `fire`, `dna`, `terrain`, `circuit`
|
|
686
|
-
|
|
687
|
-
Individual `render*Background` functions are also exported for custom canvas loops.
|
|
688
|
-
|
|
689
|
-
## Options Reference
|
|
690
|
-
|
|
691
|
-
Common `AsciiOptions`:
|
|
692
|
-
|
|
693
|
-
| Property | Type | Notes |
|
|
694
|
-
|---|---|---|
|
|
695
|
-
| `fontSize` | `number` | Main detail/performance knob. |
|
|
696
|
-
| `charSpacing` | `number` | Cell spacing multiplier. |
|
|
697
|
-
| `brightness` | `number` | `-1` to `1`. |
|
|
698
|
-
| `contrast` | `number` | Positive increases contrast. |
|
|
699
|
-
| `charset` | `string` | Use `CHARSETS`. |
|
|
700
|
-
| `colorMode` | `'grayscale' | 'fullcolor' | 'matrix' | 'accent'` | Fullcolor is fast-path capable in `1.0.91+`. |
|
|
701
|
-
| `accentColor` | `string` | Used for accent/matrix-style rendering. |
|
|
702
|
-
| `invert` | `boolean | 'auto'` | Use `'auto'` for light/dark themes. |
|
|
703
|
-
| `renderMode` | `'ascii' | 'dots'` | Dots is richer/heavier. |
|
|
704
|
-
| `animationStyle` | `AnimationStyle` | Keep `'none'` for max FPS. |
|
|
705
|
-
| `animationSpeed` | `number` | Animation speed multiplier. |
|
|
706
|
-
| `dotSizeRatio` | `number` | Dot size for dots mode. |
|
|
707
|
-
| `ditherStrength` | `number` | Use lightly for video. |
|
|
708
|
-
| `hoverStrength` | `number` | Set `0` for fast media. |
|
|
709
|
-
| `hoverRadius` | `number` | Hover influence radius. |
|
|
710
|
-
| `hoverEffect` | `HoverEffect` | Spotlight/magnify/etc. |
|
|
711
|
-
| `hoverColor` | `string` | Hover tint. |
|
|
712
|
-
| `artStyle` | `ArtStyle` | Preset name. |
|
|
713
|
-
| `customText` | `string` | Repeating custom text. |
|
|
714
|
-
| `chromaKey` | `boolean | string | {r,g,b} | null` | Green/blue/custom keying. |
|
|
715
|
-
| `chromaKeyTolerance` | `number` | Default around `60`; raise for noisy footage. |
|
|
716
|
-
| `normalize` | `boolean` | Stretch source luminance. |
|
|
717
|
-
| `charsetFrames` | `string[]` | Animated charset sequence; heavier. |
|
|
718
|
-
| `charsetFps` | `number` | Charset sequence rate. |
|
|
719
|
-
|
|
720
|
-
## Charsets And Styles
|
|
721
|
-
|
|
722
|
-
Use:
|
|
723
|
-
|
|
724
|
-
```ts
|
|
725
|
-
import { CHARSETS, ART_STYLE_PRESETS } from 'asciify-engine';
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
Common charsets:
|
|
729
|
-
|
|
730
|
-
- `CHARSETS.standard`
|
|
731
|
-
- `CHARSETS.dense`
|
|
732
|
-
- `CHARSETS.blocks`
|
|
733
|
-
- `CHARSETS.braille`
|
|
734
|
-
- `CHARSETS.lines`
|
|
735
|
-
- `CHARSETS.dots`
|
|
736
|
-
- `CHARSETS.letters`
|
|
737
|
-
- `CHARSETS.katakana`
|
|
738
|
-
- `CHARSETS.circles`
|
|
739
|
-
- `CHARSETS.geometric`
|
|
740
|
-
- `CHARSETS.shadows`
|
|
741
|
-
- `CHARSETS.starfield`
|
|
742
|
-
|
|
743
|
-
Common art styles:
|
|
744
|
-
|
|
745
|
-
- `classic`: standard ASCII.
|
|
746
|
-
- `art`: dense fullcolor detail.
|
|
747
|
-
- `particles`: dots/fullcolor.
|
|
748
|
-
- `letters`: alphabet characters.
|
|
749
|
-
- `terminal`: matrix green.
|
|
750
|
-
- `braille`: high detail.
|
|
751
|
-
- `box`, `lines`, `katakana`, `emoji`, `circles`, `shadows`, `geometric`, `waves`, `shards`, `smoke`.
|
|
752
|
-
|
|
753
|
-
## Hover And Animation
|
|
754
|
-
|
|
755
|
-
Hover effects:
|
|
756
|
-
|
|
757
|
-
`spotlight`, `magnify`, `repel`, `glow`, `colorShift`, `attract`, `shatter`, `trail`, `glitchText`
|
|
758
|
-
|
|
759
|
-
Hover presets:
|
|
760
|
-
|
|
761
|
-
`none`, `subtle`, `flashlight`, `magnifier`, `forceField`, `neon`, `fire`, `ice`, `gravity`, `shatter`, `ghost`, `glitchReveal`
|
|
762
|
-
|
|
763
|
-
Animation styles:
|
|
764
|
-
|
|
765
|
-
`none`, `wave`, `pulse`, `rain`, `breathe`, `sparkle`, `glitch`, `spiral`, `typewriter`, `scatter`, `waveField`, `ripple`, `melt`, `orbit`, `cellular`
|
|
766
|
-
|
|
767
|
-
Best practice:
|
|
768
|
-
|
|
769
|
-
- For video backgrounds and scroll heroes, use `animationStyle: 'none'` and `hoverStrength: 0`.
|
|
770
|
-
- For interactive hover demos, keep the canvas smaller or use `fontSize >= 8`.
|
|
771
|
-
- Avoid combining tiny fonts, fullcolor, hover, and animation unless the visual really needs it.
|
|
772
|
-
|
|
773
|
-
## Recording And Export
|
|
774
|
-
|
|
775
|
-
```ts
|
|
776
|
-
import { createRecorder, recordAndDownload } from 'asciify-engine';
|
|
777
|
-
|
|
778
|
-
await recordAndDownload(canvas, { duration: 3000, filename: 'ascii-art' });
|
|
779
|
-
|
|
780
|
-
const recorder = createRecorder(canvas, { fps: 30 });
|
|
781
|
-
recorder.start();
|
|
782
|
-
const blob = await recorder.stop();
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
## Type Imports
|
|
786
|
-
|
|
787
|
-
```ts
|
|
788
|
-
import type {
|
|
789
|
-
AsciiOptions,
|
|
790
|
-
AsciiCell,
|
|
791
|
-
AsciiFrame,
|
|
792
|
-
AsciiTextFrame,
|
|
793
|
-
AsciifySimpleOptions,
|
|
794
|
-
AsciifyVideoOptions,
|
|
795
|
-
VideoScrollScrubOptions,
|
|
796
|
-
ColorMode,
|
|
797
|
-
AnimationStyle,
|
|
798
|
-
ArtStyle,
|
|
799
|
-
HoverEffect,
|
|
800
|
-
} from 'asciify-engine';
|
|
801
|
-
```
|
|
128
|
+
Do not import nonexistent helpers such as `createRecorder` or `recordAndDownload` from 1.1.0. For recording, use a browser `MediaRecorder` with a supported `canvas.captureStream()` format and clean up its tracks; for snapshots, inspect the published `captureSnapshot` / `snapshotAndDownload` types.
|