Skip to content

Latest commit

 

History

History
344 lines (241 loc) · 11.7 KB

API.md

File metadata and controls

344 lines (241 loc) · 11.7 KB

API Reference

Package entry points

Import Description
lascii Main entry. Side-effect free; exports classes and init / autoInitDom.
lascii/auto Auto-initializes on DOMContentLoaded via autoInitDom() (side-effectful).
lascii/dom DOM adapter exports (LasciiTextEffect, LasciiImageEffect, initDom, autoInitDom). Side-effect free.
lascii/core/text LasciiTextEffect only.
lascii/core/image LasciiImageEffect only.

Use lascii or lascii/core/* when you want full control and no side effects on import. Use lascii/auto for declarative data-lascii-* setup.


lascii exports

import lascii, {
  LasciiTextEffect,
  LasciiImageEffect,
  init,
  autoInitDom,
} from "lascii";
Export Type Description
LasciiTextEffect class Scramble/reveal text animation.
LasciiImageEffect class ASCII canvas reveal for images.
init function Scans the DOM and starts effects (initDom).
autoInitDom function Registers init on DOMContentLoaded, or runs immediately if the document is ready.
InitDomOptions type Options for init / autoInitDom ({ lazy?: boolean }).
LasciiEvent object Event name constants: start, progress, complete, error.
default object { LasciiTextEffect, LasciiImageEffect, init, autoInitDom }.

init() / autoInitDom()

init() (alias of initDom) runs:

  • LasciiImageEffect.init("[data-lascii-image]")
  • LasciiTextEffect.init("[data-lascii-text]")

Pass { lazy: true } to defer creation until each element is near the viewport (Intersection Observer with rootMargin: "100px"). This reduces startup work on pages with many effects, especially image sampling. If IntersectionObserver is unavailable, init falls back to the eager path.

import { init } from "lascii";

init({ lazy: true });

autoInitDom() calls init() when the document is ready and accepts the same options:

import { autoInitDom } from "lascii";
autoInitDom({ lazy: true });

Importing lascii does not call autoInitDom() automatically. For declarative setup:

import "lascii/auto";

Or call it yourself:

import { autoInitDom } from "lascii";
autoInitDom();

To import a single effect with maximum tree shaking:

import { LasciiTextEffect } from "lascii/core/text";
import { LasciiImageEffect } from "lascii/core/image";

Data attributes

Attribute Element Behavior
data-lascii-text Any text container Reads textContent, runs text scramble effect.
data-lascii-image <img> Samples image, ASCII animation, then fades to original.

Text: phrase separator

Multiple phrases in one element are separated by |:| (configurable via separator):

<p data-lascii-text>First|:|Second|:|Third</p>

When the separator is present, phrases loop with phraseDelay between transitions.

Image: layout requirements

Place the image inside a positioned wrapper with overflow hidden and a defined aspect ratio (e.g. aspect-ratio: 4/5):

<div style="position: relative; aspect-ratio: 4/5; overflow: hidden;">
  <img data-lascii-image src="photo.jpg" alt="photo" />
</div>

Cross-origin images need CORS headers on the image server (crossOrigin = "anonymous" is set internally).


LasciiTextEffect

import { LasciiTextEffect } from "lascii";
// or
import LasciiTextEffect from "lascii/core/text";

Constructor

new LasciiTextEffect(element, options?)
  • element — DOM node whose textContent is the source string.
  • options — Partial override of LasciiTextEffect.DEFAULTS.

On construction, the element’s text is cleared. The first animation is scheduled on a microtask, so you can attach lifecycle listeners immediately after new.

Static members

LasciiTextEffect.RevealOrigin

Key Value Effect
START "start" Reveal progresses from the start of the string.
MIDDLE "middle" Reveal radiates from the center outward.

LasciiTextEffect.DEFAULTS

Option Type Default Description
introChars string "█▓▒░x92" Character sequence shown at the start of each cell’s scramble.
introPhaseFrames number 10 Frames to step through introChars before random chars.
chars string "!<>-_\\/[]{}—=+*^?#________" Pool of random scramble characters.
frameStartMax number 40 Max frames before a character begins scrambling (spread along string).
frameEndMax number 40 Random extra scramble length cap per character.
randomCharChance number 0.28 Probability of picking a new random char each frame.
phraseDelay number 800 Ms between phrases when looping (`
separator string `"|: "`
revealOrigin string "start" "start" or "middle" (RevealOrigin).

reducedMotion is a constructor option (not a default): true skips animation, false forces it, omitted follows prefers-reduced-motion. See Accessibility.

Scramble characters are rendered in <span class="dud"> — style .dud in your CSS if needed.

Instance methods

Method Returns Description
setText(newText) Promise<void> Animates from current text to newText. Resolves when complete (3s safety timeout).

Both effects extend EventTarget and emit lifecycle events (see Lifecycle events).

Static methods

LasciiTextEffect.init(selector = "[data-lascii-text]")

Creates one LasciiTextEffect per matching element.

Example

const effect = new LasciiTextEffect(document.querySelector(".headline"), {
  phraseDelay: 1200,
  revealOrigin: LasciiTextEffect.RevealOrigin.MIDDLE,
});

effect.addEventListener("complete", (event) => {
  console.log("Effect completed:", event.detail.text);
});

await effect.setText("Updated copy");

LasciiImageEffect

import { LasciiImageEffect } from "lascii";
// or
import LasciiImageEffect from "lascii/core/image";

Constructor

new LasciiImageEffect(img, index = 0, options?)
  • img — <img> element. Opacity is set to 0 until reveal; a canvas is appended to the parent.
  • index — Stagger index: delay = index * IMAGE_STAGGER_MS.
  • options — Partial override of LasciiImageEffect.DEFAULTS.

LasciiImageEffect.DEFAULTS

Option Type Default Description
ASCII_CHARS string " . . . . . . :::=+xX#0369" Light-to-dark character ramp for luminance mapping.
FONT_SIZE number 40 Monospace font size used for measurement and drawing.
ASPECT_WIDTH number 4 Target crop aspect (width).
ASPECT_HEIGHT number 5 Target crop aspect (height).
ASCII_COLUMNS number 25 Minimum column count (may increase with container width).
MAX_ASCII_COLUMNS number 96 Upper cap when scaling to container width.
TARGET_CELL_CSS_PX number 9 Target cell size in CSS pixels for column scaling.
IMAGE_STAGGER_MS number 100 Delay multiplier per image index.
CELL_APPEAR_MS number 0.5 Delay between starting each cell animation.
SCRAMBLE_COUNT number 10 Scramble frames for “dense” (dark) cells.
SCRAMBLE_SPEED_MS number 50 Interval between scramble frame updates.
REVEAL_DELAY_MS number 0 Delay before fading canvas out and showing the image.
BACKGROUND_COLOR string "transparent" Canvas cell background.
TEXT_COLOR string "#c8c8c8" ASCII character color.

reducedMotion is a constructor option (not a default): true skips the ASCII animation and shows the original image, false forces animation, omitted follows prefers-reduced-motion.

Column count is recalculated from the image’s displayed width:
cols = clamp(ASCII_COLUMNS, round(width / TARGET_CELL_CSS_PX), MAX_ASCII_COLUMNS).

Static methods

LasciiImageEffect.init(selector = "[data-lascii-image]")

Creates one LasciiImageEffect per matching image, with index from forEach order.

Both effects extend EventTarget and emit lifecycle events (see Lifecycle events). For images, start / complete detail.text is img.alt or, if empty, img.src.

Example

document.querySelectorAll("[data-lascii-image]").forEach((img, index) => {
  new LasciiImageEffect(img, index, {
    SCRAMBLE_COUNT: 20,
    TEXT_COLOR: "#ffffff",
  });
});

Lifecycle events

LasciiTextEffect and LasciiImageEffect extend EventTarget. Attach listeners after construction; the first animation turn waits one microtask so start is not missed.

Event When detail
start Animation begins { text: string }
progress During the animation { progress: number }
complete Animation finished { text: string }
error Recoverable runtime failure { error: Error }

progress is a number from 0 to 1. Looping text effects emit start / complete once per phrase.

import { LasciiEvent, LasciiTextEffect } from "lascii";

const effect = new LasciiTextEffect(element);

effect.addEventListener(LasciiEvent.Complete, (event) => {
  console.log("Effect completed:", event.detail.text);
});

effect.addEventListener("error", (event) => {
  console.warn(event.detail.error);
});

Accessibility

Effects follow prefers-reduced-motion: reduce (WCAG 2.3.3 / motion preferences):

  • Text — the target phrase is applied immediately; scramble/requestAnimationFrame is skipped. Looped phrases still advance after phraseDelay, without animation.
  • Image — the original <img> stays visible; canvas sampling and cell animation do not run.

Override with { reducedMotion: true } or { reducedMotion: false }.

Screen readers

LasciiTextEffect treats the host as a live region:

Attribute When Purpose
aria-live="polite" If the author did not set aria-live Announce phrase changes without interrupting
aria-atomic="true" If missing Read the whole phrase
aria-busy="true" and aria-label During scramble Expose the destination text instead of random characters
(remove busy/label) When complete Accessible name falls back to visible textContent

LasciiImageEffect sets aria-hidden="true" on the decorative canvas and aria-busy="true" on the image while the ASCII overlay is running (cleared on reveal, error, or dispose). Prefer a meaningful alt on the <img>.


Import patterns

Declarative (auto-init)

<script type="module">
  import "lascii/auto";
</script>

Manual init (side-effect free)

import { LasciiImageEffect, LasciiTextEffect, init } from "lascii";

init();

Or with maximum tree shaking:

import LasciiTextEffect from "lascii/core/text";
import LasciiImageEffect from "lascii/core/image";
import { initDom } from "lascii/dom";

initDom();

Tree-shaking / side effects

Only ./dist/auto.js and ./dist/auto.cjs are marked as side-effectful in package.json. All other entry points are tree-shakeable:

  • import { LasciiTextEffect } from "lascii" — can drop unused image code
  • import from "lascii/core/text" — text effect only
  • import "lascii/auto" — keeps the auto-init side effect (intentional)