/** * ScrollTrigger * * Triggers timelines based on scroll position: * - start/end parameters define trigger zone (GSAP-style) * - scrub links animation progress to scroll position * - scrub: number adds smooth lag (in seconds) * - scroller: custom scroll container (default: window) * - pin: fix element in place during animation * - markers shows debug markers (optional) * * Pin implementation: * - Window scroller: uses position:fixed (seamless, no jitter) * - Custom scroller: uses transform (slight lag unavoidable) * * Start/End format: " " * - Keywords: top, center, bottom * - Units: 100px, 50%, 20vh * - Relative: +=500px (for end only) */ import type { ScrollConfig } from '../types'; import type { Timeline } from '../core/Timeline'; import { BaseTrigger } from './BaseTrigger'; export declare class ScrollTrigger extends BaseTrigger { private static _nextId; private _id; private static readonly _SCRUB_TICKER_PRIORITY; private static readonly _TINY_RANGE_PX; private static _activeInstances; private static _loadListenerAdded; private _scrollListener?; private _scrubTickListener; private _currentProgress; private _targetProgress; private _scrubLag; private _scroller; private _triggerStart; private _triggerEnd; private _pinManager; private _markerManager; private _triggerState; private _toggleActions; private _initializing; constructor(timeline: Timeline, config: ScrollConfig); /** * Register the global window.load listener (once). * After all resources finish loading, refresh every active ScrollTrigger * so trigger positions account for layout shifts caused by images/fonts. */ private static _ensureLoadListener; private _resolveScroller; private _resolvePinElement; /** * Default start position — matches GSAP behavior: * - With pin: 'top top' (element top hits viewport top) * - Without pin: 'top bottom' (element top hits viewport bottom) */ private _defaultStart; /** * Default end position — matches GSAP behavior: * 'bottom top' (element bottom hits viewport top) */ private _defaultEnd; private _getFirstAnimatedElement; /** * Resolve the trigger element from config or first animation */ private _resolveTriggerElement; /** * Resolve the element the `end` position is measured against (GSAP `endTrigger` * parity). Returns null when no `endTarget` is configured or it matches nothing, * in which case `end` is measured against the start/trigger element — the * default GSAP behaviour. */ private _resolveEndTargetElement; /** * Calculate trigger start/end scroll positions based on config. * * Pin distance equals the trigger range (triggerEnd - triggerStart). * The PinManager spacer adds exactly that many pixels of scroll room to the * page, so the animation always plays over the full configured distance while * the element is pinned — no separate "extension" step is needed. * * When refresh() is called while the element is position:fixed (pinned), we * use the spacer's rect instead of the element's rect. A position:fixed * element returns viewport-relative coordinates from getBoundingClientRect(), * which would produce incorrect document-relative trigger positions. The * spacer sits in the element's original place in the document flow, so its * rect always reflects the correct base for the calculation. */ private _calculateTriggerPositions; protected _onEnable(): void; protected _onDisable(): void; /** * Refresh trigger positions (call after layout changes like resize) */ refresh(): void; private _getViewportHeight; private _getScrollTop; private _getScrollHeight; private _onScroll; /** * Apply snap to a raw progress value based on config.snap. * - number: snap to evenly-spaced increments (e.g. 0.25 → 0, 0.25, 0.5, 0.75, 1) * - number[]: snap to nearest value in array * - function: custom snap function */ private _applySnap; private _startSmoothScrollLoop; private _stopSmoothScrollLoop; }