createScrollProgress
Subscribe an element. onProgress fires whenever
the mapped progress changes. The returned handle's
destroy() unsubscribes. Repeated equal values
are de-duped.
import { createScrollProgress } from "@vysmo/scroll";
interface ScrollProgressOptions {
element: HTMLElement;
ease?: (t: number) => number;
onProgress: (progress: number) => void;
}
declare function createScrollProgress(opts: ScrollProgressOptions): {
destroy(): void;
};
createScrollTransition
Drive a transition's progress through the section's sweep.
You hand in the runner; we wire the
render() call. Multiple scroll-transitions can
share one runner.
import { createScrollTransition, scrollPlateau } from "@vysmo/scroll";
import { Runner, crossZoom } from "@vysmo/transitions";
const runner = new Runner({ canvas });
const handle = createScrollTransition({
section,
runner,
transition: crossZoom,
from, to,
params: { speed: 1.2 },
ease: scrollPlateau(0.3, 0.7),
});
createScrollEffect
Drive an effect's params from progress. paramsAt
decouples the scroll package from effect-specific knowledge
— the caller maps progress to whichever uniform makes
sense.
import { createScrollEffect, scrollZones } from "@vysmo/scroll";
import { Runner, blur } from "@vysmo/effects";
const runner = new Runner({ canvas });
const handle = createScrollEffect({
section,
runner,
effect: blur,
source,
paramsAt: (p) => ({ radius: p * 24 }),
ease: scrollZones(0.25, 0.75),
});
Envelopes — scrollRange / scrollZones / scrollPlateau
Pure functions that reshape [0, 1]. Use them as
the ease argument on any primitive
(scrollPlateau for transitions that hold mid-section,
scrollZones for effects that go quiet in the
middle, scrollRange for clamped sub-ranges).
smoothstep is the default ramp shape.
import { scrollRange, scrollZones, scrollPlateau, smoothstep } from "@vysmo/scroll";
scrollRange(start, end, ease?);
scrollZones(clearStart, clearEnd, ease?);
scrollPlateau(clearStart, clearEnd, ease?);
smoothstep;
sharedScrollObserver / ScrollObserver
The singleton (use it for everything) and the class (for
isolated observers in unusual cases). flush() is
exposed so callers can force a redraw after changing local
state (e.g., a slider that reshapes an envelope) without
waiting for the next scroll event.
import { sharedScrollObserver, ScrollObserver } from "@vysmo/scroll";
const observer = sharedScrollObserver();
const unsubscribe = observer.subscribe(element, {
onScroll(rect, viewport) {
},
});
const local = new ScrollObserver();
Types
EaseFn = (t: number) => number —
structurally compatible with
@vysmo/easings.EasingFn, kept local so
this package has zero runtime coupling.
Handle = { destroy(): void } — the
uniform return shape of every primitive. Always call
destroy() on unmount.