@cosmictraveler002/anim-kit 1.3.0 → 1.4.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 +83 -11
- package/dist/anim-kit.standalone.js +5 -5
- package/dist/anim-kit.standalone.js.map +1 -1
- package/dist/effects/drag-rail.d.ts +9 -1
- package/dist/effects/drag-rail.d.ts.map +1 -1
- package/dist/effects/drag-rail.js +57 -18
- package/dist/effects/drag-rail.js.map +1 -1
- package/dist/three/gl-rail.d.ts +29 -0
- package/dist/three/gl-rail.d.ts.map +1 -0
- package/dist/three/gl-rail.js +350 -0
- package/dist/three/gl-rail.js.map +1 -0
- package/dist/three/index.d.ts +3 -1
- package/dist/three/index.d.ts.map +1 -1
- package/dist/three/index.js +2 -1
- package/dist/three/index.js.map +1 -1
- package/package.json +1 -1
- package/src/effects/drag-rail.ts +67 -18
- package/src/three/gl-rail.ts +437 -0
- package/src/three/index.ts +3 -1
|
@@ -2,6 +2,8 @@ import type { CommonOptions, Destroy, TargetLike } from "../core/types.js";
|
|
|
2
2
|
export interface DragRailOptions extends CommonOptions {
|
|
3
3
|
/** Scroll viewport around the track — defaults to `track.parentElement`. */
|
|
4
4
|
viewport?: TargetLike;
|
|
5
|
+
/** Motion axis — `"auto"` flips vertical when only the column overflows. @default `"x"` */
|
|
6
|
+
axis?: "x" | "y" | "auto";
|
|
5
7
|
/** Children that tilt with velocity. @default `":scope > *"` */
|
|
6
8
|
item?: string;
|
|
7
9
|
/** Follow speed toward the intent, per 60fps frame (0..1). @default 0.1 */
|
|
@@ -16,8 +18,14 @@ export interface DragRailOptions extends CommonOptions {
|
|
|
16
18
|
tilt?: number;
|
|
17
19
|
/** Tilt clamp, degrees. @default 8 */
|
|
18
20
|
tiltMax?: number;
|
|
19
|
-
/** `(pos, velocity) => {}` called every rendered frame while mounted. */
|
|
21
|
+
/** `(pos, velocity) => {}` called every rendered frame while mounted (pos along the active axis). */
|
|
20
22
|
onTick?: (pos: number, velocity: number) => void;
|
|
21
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* The axis rule shared by `dragRail` and `glRail`: fixed when asked, otherwise
|
|
26
|
+
* the layout decides — a rail only runs vertical when the *column* overflows
|
|
27
|
+
* and the row doesn't (a mobile stack), everything else is horizontal.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveRailAxis(track: HTMLElement, viewport: HTMLElement, pref: "x" | "y" | "auto"): "x" | "y";
|
|
22
30
|
export declare function dragRail(target: TargetLike, options?: DragRailOptions): Destroy;
|
|
23
31
|
//# sourceMappingURL=drag-rail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drag-rail.d.ts","sourceRoot":"","sources":["../../src/effects/drag-rail.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drag-rail.d.ts","sourceRoot":"","sources":["../../src/effects/drag-rail.ts"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3E,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAC1B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qGAAqG;IACrG,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,GACvB,GAAG,GAAG,GAAG,CAKX;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAiMnF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Drag rail — the bounded, inertia-driven horizontal
|
|
2
|
+
* Drag rail — the bounded, inertia-driven rail (horizontal or vertical).
|
|
3
3
|
*
|
|
4
4
|
* A grab-and-throw rail with real physics, extracted from the drag-driven
|
|
5
5
|
* portfolio rail pattern: pointer drag, wheel and trackpad all feed one
|
|
@@ -29,11 +29,18 @@
|
|
|
29
29
|
* - **Velocity-reactive items.** `tilt` rotates children proportionally to the
|
|
30
30
|
* rendered per-frame velocity (the cards lean into motion and spring flat at
|
|
31
31
|
* rest); `onTick` exposes pos/velocity for WebGL or custom consumers.
|
|
32
|
+
* - **Two axes.** `axis: "x"` (default), `"y"`, or `"auto"` — under `auto`
|
|
33
|
+
* the *layout* decides via `resolveRailAxis()` (only the column overflows →
|
|
34
|
+
* vertical, otherwise horizontal; the same rule glRail uses to pick its
|
|
35
|
+
* bend axis). touch-action claims the rail's own gesture axis (`pan-y` for
|
|
36
|
+
* a horizontal rail, `pan-x` for a vertical one) so the page never fights
|
|
37
|
+
* the rail for a swipe, and a mid-life flip re-keys the transform instead
|
|
38
|
+
* of leaving the stale axis behind.
|
|
32
39
|
* - **Fidelity.** `destroy()` removes every listener + the ticker, kills the
|
|
33
40
|
* tilt state and restores the inline cursor/user-select/touch-action the
|
|
34
41
|
* effect had overwritten.
|
|
35
42
|
*
|
|
36
|
-
* dragRail(".ak-rail-track", { tilt: 0.05 })
|
|
43
|
+
* dragRail(".ak-rail-track", { tilt: 0.05, axis: "auto" })
|
|
37
44
|
*
|
|
38
45
|
* CSS: viewport `overflow: hidden`; track `display: flex; width: max-content;
|
|
39
46
|
* gap: 1rem; cursor: grab; user-select: none; touch-action: pan-y`.
|
|
@@ -41,12 +48,24 @@
|
|
|
41
48
|
import { gsap, initGSAP } from "../core/gsap.js";
|
|
42
49
|
import { guard } from "../core/guard.js";
|
|
43
50
|
import { one, toArray } from "../core/util.js";
|
|
51
|
+
/**
|
|
52
|
+
* The axis rule shared by `dragRail` and `glRail`: fixed when asked, otherwise
|
|
53
|
+
* the layout decides — a rail only runs vertical when the *column* overflows
|
|
54
|
+
* and the row doesn't (a mobile stack), everything else is horizontal.
|
|
55
|
+
*/
|
|
56
|
+
export function resolveRailAxis(track, viewport, pref) {
|
|
57
|
+
if (pref !== "auto")
|
|
58
|
+
return pref;
|
|
59
|
+
const overflowY = track.scrollHeight - viewport.clientHeight;
|
|
60
|
+
const overflowX = track.scrollWidth - viewport.clientWidth;
|
|
61
|
+
return overflowY > 0 && overflowX <= 0 ? "y" : "x";
|
|
62
|
+
}
|
|
44
63
|
export function dragRail(target, options = {}) {
|
|
45
64
|
initGSAP();
|
|
46
65
|
const track = one(target);
|
|
47
66
|
if (!track)
|
|
48
67
|
return () => { };
|
|
49
|
-
const { viewport, item = ":scope > *", lerp = 0.1, edge = 140, throwScale = 14, wheel = true, tilt = 0, tiltMax = 8, onTick, } = options;
|
|
68
|
+
const { viewport, axis: axisOpt = "x", item = ":scope > *", lerp = 0.1, edge = 140, throwScale = 14, wheel = true, tilt = 0, tiltMax = 8, onTick, } = options;
|
|
50
69
|
return guard(options, () => {
|
|
51
70
|
const vp = one(viewport) ?? track.parentElement ?? track;
|
|
52
71
|
const prevStyle = {
|
|
@@ -55,13 +74,24 @@ export function dragRail(target, options = {}) {
|
|
|
55
74
|
touchAction: track.style.touchAction,
|
|
56
75
|
};
|
|
57
76
|
/* ---------------- bounds ---------------- */
|
|
58
|
-
let
|
|
77
|
+
let axis = resolveRailAxis(track, vp, axisOpt);
|
|
78
|
+
let flipped = false; // axis changed mid-life → force a transform re-key
|
|
79
|
+
let min = 0; // most-negative resting position (content overflows)
|
|
59
80
|
let max = 0; // start of the rail
|
|
60
|
-
let pos = 0; // rendered
|
|
61
|
-
let intent = 0; // wanted
|
|
81
|
+
let pos = 0; // rendered position
|
|
82
|
+
let intent = 0; // wanted position (drag/wheel/throw feed this)
|
|
62
83
|
const measure = () => {
|
|
63
|
-
const
|
|
64
|
-
|
|
84
|
+
const next = resolveRailAxis(track, vp, axisOpt);
|
|
85
|
+
if (next !== axis) {
|
|
86
|
+
axis = next;
|
|
87
|
+
flipped = true;
|
|
88
|
+
// Claim the rail's own gesture axis; the other one belongs to the page.
|
|
89
|
+
track.style.touchAction = axis === "x" ? "pan-y" : "pan-x";
|
|
90
|
+
}
|
|
91
|
+
const overflow = axis === "x"
|
|
92
|
+
? track.scrollWidth - vp.clientWidth
|
|
93
|
+
: track.scrollHeight - vp.clientHeight;
|
|
94
|
+
min = -Math.max(0, overflow);
|
|
65
95
|
max = 0;
|
|
66
96
|
// Fold an out-of-range position back through the soft edge (no jump).
|
|
67
97
|
intent = soft(intent);
|
|
@@ -77,14 +107,15 @@ export function dragRail(target, options = {}) {
|
|
|
77
107
|
}
|
|
78
108
|
/* ---------------- pointer drag ---------------- */
|
|
79
109
|
let dragging = false;
|
|
80
|
-
let
|
|
110
|
+
let last = 0; // last pointer coordinate along the active axis
|
|
81
111
|
let velocity = 0; // smoothed pointer delta (px/frame-ish)
|
|
82
112
|
let renderedVel = 0; // rendered per-frame velocity (drives tilt/onTick)
|
|
113
|
+
const along = (e) => axis === "x" ? e.clientX : e.clientY;
|
|
83
114
|
const onPointerDown = (e) => {
|
|
84
115
|
if (e.pointerType === "mouse" && e.button !== 0)
|
|
85
116
|
return;
|
|
86
117
|
dragging = true;
|
|
87
|
-
|
|
118
|
+
last = along(e);
|
|
88
119
|
velocity = 0;
|
|
89
120
|
try {
|
|
90
121
|
vp.setPointerCapture(e.pointerId);
|
|
@@ -97,10 +128,10 @@ export function dragRail(target, options = {}) {
|
|
|
97
128
|
const onPointerMove = (e) => {
|
|
98
129
|
if (!dragging)
|
|
99
130
|
return;
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
velocity = velocity * 0.7 +
|
|
103
|
-
intent = soft(intent +
|
|
131
|
+
const delta = along(e) - last;
|
|
132
|
+
last = along(e);
|
|
133
|
+
velocity = velocity * 0.7 + delta * 0.3; // smooth out event-rate jitter
|
|
134
|
+
intent = soft(intent + delta);
|
|
104
135
|
};
|
|
105
136
|
const endDrag = (e) => {
|
|
106
137
|
if (!dragging)
|
|
@@ -125,7 +156,13 @@ export function dragRail(target, options = {}) {
|
|
|
125
156
|
const onWheel = (e) => {
|
|
126
157
|
if (!wheel)
|
|
127
158
|
return;
|
|
128
|
-
const delta =
|
|
159
|
+
const delta = axis === "x"
|
|
160
|
+
? Math.abs(e.deltaX) > Math.abs(e.deltaY)
|
|
161
|
+
? e.deltaX
|
|
162
|
+
: e.deltaY
|
|
163
|
+
: e.deltaY;
|
|
164
|
+
if (!delta)
|
|
165
|
+
return;
|
|
129
166
|
const bound = delta > 0 ? max : min;
|
|
130
167
|
const outward = (intent - bound) * (delta > 0 ? 1 : -1);
|
|
131
168
|
if (outward > edge)
|
|
@@ -149,9 +186,11 @@ export function dragRail(target, options = {}) {
|
|
|
149
186
|
const prev = pos;
|
|
150
187
|
pos += (intent - pos) * Math.min(1, lerp * ratio);
|
|
151
188
|
renderedVel = pos - prev;
|
|
152
|
-
if (renderedVel === 0 && pos === intent)
|
|
189
|
+
if (renderedVel === 0 && pos === intent && !flipped)
|
|
153
190
|
return; // idle: skip the write
|
|
154
|
-
|
|
191
|
+
flipped = false;
|
|
192
|
+
// Re-key both axes: a flip must clear the stale one, never leave it behind.
|
|
193
|
+
gsap.set(track, axis === "x" ? { x: pos, y: 0 } : { x: 0, y: pos });
|
|
155
194
|
if (items.length) {
|
|
156
195
|
gsap.set(items, {
|
|
157
196
|
rotation: gsap.utils.clamp(-tiltMax, tiltMax, renderedVel * tilt),
|
|
@@ -164,7 +203,7 @@ export function dragRail(target, options = {}) {
|
|
|
164
203
|
track.dataset.akRail = "true";
|
|
165
204
|
track.style.cursor = "grab";
|
|
166
205
|
track.style.userSelect = "none";
|
|
167
|
-
track.style.touchAction = "pan-y";
|
|
206
|
+
track.style.touchAction = axis === "x" ? "pan-y" : "pan-x";
|
|
168
207
|
vp.addEventListener("pointerdown", onPointerDown);
|
|
169
208
|
vp.addEventListener("pointermove", onPointerMove);
|
|
170
209
|
vp.addEventListener("pointerup", onPointerUp);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drag-rail.js","sourceRoot":"","sources":["../../src/effects/drag-rail.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"drag-rail.js","sourceRoot":"","sources":["../../src/effects/drag-rail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CommonOptions, Destroy, TargetLike } from "../core/types.js";
|
|
2
|
+
export interface GlRailOptions extends CommonOptions {
|
|
3
|
+
/** Stage around the track — the canvas covers it. Defaults to `track.parentElement`. */
|
|
4
|
+
viewport?: TargetLike;
|
|
5
|
+
/** Cards re-rendered on the canvas — each needs an `<img>`. @default `":scope > *"` */
|
|
6
|
+
card?: string;
|
|
7
|
+
/** Motion + bend axis: `"x"`, `"y"`, or the layout's choice. @default `"auto"` */
|
|
8
|
+
axis?: "x" | "y" | "auto";
|
|
9
|
+
/** Cylinder radius the cards bend around, px — smaller = stronger bend. @default 1200 */
|
|
10
|
+
radius?: number;
|
|
11
|
+
/** Corner radius, px (rounded-box SDF in the fragment shader). @default 16 */
|
|
12
|
+
corner?: number;
|
|
13
|
+
/** Perspective grid floor under the cards. @default true */
|
|
14
|
+
grid?: boolean;
|
|
15
|
+
/** Device-pixel-ratio cap. @default 2 */
|
|
16
|
+
dpr?: number;
|
|
17
|
+
/** Follow speed toward the intent, per 60fps frame (0..1). @default 0.1 */
|
|
18
|
+
lerp?: number;
|
|
19
|
+
/** Rubber-band resistance distance past the ends, px. @default 140 */
|
|
20
|
+
edge?: number;
|
|
21
|
+
/** Momentum multiplier on release. @default 14 */
|
|
22
|
+
throwScale?: number;
|
|
23
|
+
/** Wheel / trackpad drives the rail (consumed while it can still move). @default true */
|
|
24
|
+
wheel?: boolean;
|
|
25
|
+
/** `(pos, velocity) => {}` called every rendered frame while mounted. */
|
|
26
|
+
onTick?: (pos: number, velocity: number) => void;
|
|
27
|
+
}
|
|
28
|
+
export declare function glRail(target: TargetLike, options?: GlRailOptions): Destroy;
|
|
29
|
+
//# sourceMappingURL=gl-rail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gl-rail.d.ts","sourceRoot":"","sources":["../../src/three/gl-rail.ts"],"names":[],"mappings":"AAuDA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3E,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,wFAAwF;IACxF,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAC1B,yFAAyF;IACzF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAsFD,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CA4Q/E"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GL rail — the WebGL overlay rail: physics below, bent cards above.
|
|
3
|
+
*
|
|
4
|
+
* `dragRail` owns the motion (intent/pos ticker, tanh rubber-band, throw
|
|
5
|
+
* momentum, Lenis-safe wheel, auto axis); this effect adds the GPU layer the
|
|
6
|
+
* flat DOM can't draw: every card re-rendered onto **one fixed canvas** whose
|
|
7
|
+
* surfaces bend around an invisible cylinder, over a perspective grid floor.
|
|
8
|
+
* Why it is shaped this way (audit notes):
|
|
9
|
+
*
|
|
10
|
+
* - **The DOM stays the source of truth.** Cards keep owning layout, labels,
|
|
11
|
+
* hit areas and alt text; each frame reads their viewport rects and the
|
|
12
|
+
* shader re-creates the pixels *beneath* the labels. A label never drifts
|
|
13
|
+
* off its card, because the card **is** the rect the label sits in — only
|
|
14
|
+
* the picture curves.
|
|
15
|
+
* - **The bend lives in the vertex shader.** Each vertex takes its offset
|
|
16
|
+
* along the rail axis (`uOffset + local`), maps it onto a cylinder of
|
|
17
|
+
* `uRadius` (`a = o / R`, `x = R·sin a`, `z = −R·(1−cos a)`) and re-centres
|
|
18
|
+
* so the card's middle stays glued to its DOM position while its edges
|
|
19
|
+
* foreshorten onto the curve. One uniform per card, no per-vertex CPU work
|
|
20
|
+
* — and the rotation the cards need arrives free from the bend itself.
|
|
21
|
+
* - **One renderer for the whole rail.** A single alpha canvas inserted
|
|
22
|
+
* *under* the track (the track's transform creates a stacking context that
|
|
23
|
+
* paints above it): labels stay DOM, card backgrounds stay transparent, and
|
|
24
|
+
* the only pixels the canvas needs are the `<img>`s it hides — each one
|
|
25
|
+
* only after its texture has actually loaded.
|
|
26
|
+
* - **The axis follows the layout.** `axis: "auto"` hands the same
|
|
27
|
+
* `resolveRailAxis()` rule to the physics *and* the bend: row overflows →
|
|
28
|
+
* horizontal rail + bend around Y, only the column overflows (mobile
|
|
29
|
+
* stack) → vertical rail + bend around X. One init serves both.
|
|
30
|
+
* - **Silent no-op ladder.** Missing target → no-op. No
|
|
31
|
+
* `WebGLRenderingContext` (jsdom, SSR, WebGL-disabled browsers) → the flat
|
|
32
|
+
* `dragRail` rail alone, *before* any context is requested (a probe call
|
|
33
|
+
* would itself log). Renderer construction throws → flat rail. Texture 404
|
|
34
|
+
* → that one card's `<img>` stays visible. Under `prefers-reduced-motion`
|
|
35
|
+
* nothing mounts at all (the outer `guard` owns that decision). Nothing
|
|
36
|
+
* ever logs.
|
|
37
|
+
* - **Fidelity.** `destroy()` unwinds the physics, then the GPU: ticker,
|
|
38
|
+
* observers, geometry, materials, textures and the renderer are disposed,
|
|
39
|
+
* the canvas is removed and image opacities + the stage's inline position
|
|
40
|
+
* are restored.
|
|
41
|
+
*
|
|
42
|
+
* glRail("[data-rail]", { radius: 1200, grid: true })
|
|
43
|
+
*
|
|
44
|
+
* CSS: the stage (viewport) `position: relative; overflow: hidden` — the
|
|
45
|
+
* canvas covers it; the track `display: flex; width: max-content; gap: 1rem;
|
|
46
|
+
* cursor: grab; user-select: none; touch-action: pan-y` (flip to a column +
|
|
47
|
+
* `width: 100%; height: max-content` for the vertical layout). Cards
|
|
48
|
+
* `position: relative` with a **transparent background** — labels paint above
|
|
49
|
+
* the canvas for free, the effect hides only the media.
|
|
50
|
+
*/
|
|
51
|
+
import * as THREE from "three";
|
|
52
|
+
import { gsap, initGSAP } from "../core/gsap.js";
|
|
53
|
+
import { guard } from "../core/guard.js";
|
|
54
|
+
import { one, toArray } from "../core/util.js";
|
|
55
|
+
import { dragRail, resolveRailAxis } from "../effects/drag-rail.js";
|
|
56
|
+
/* Card: the cylinder bend in the vertex shader, cover-crop + SDF corners in
|
|
57
|
+
the fragment — the pixel contract is webglMedia's, bent to the rail. */
|
|
58
|
+
const CARD_VERT = /* glsl */ `
|
|
59
|
+
varying vec2 vUv;
|
|
60
|
+
uniform vec2 uSize; // card size, px
|
|
61
|
+
uniform float uOffset; // centre offset from the stage centre along the rail axis, px
|
|
62
|
+
uniform float uRadius; // cylinder radius, px
|
|
63
|
+
uniform float uAxis; // 0 = rail runs x (bend around Y), 1 = rail runs y (bend around X)
|
|
64
|
+
|
|
65
|
+
void main() {
|
|
66
|
+
vUv = uv;
|
|
67
|
+
vec3 p = vec3(position.xy * uSize, 0.0);
|
|
68
|
+
float along = uAxis < 0.5 ? p.x : p.y;
|
|
69
|
+
float a = (uOffset + along) / uRadius;
|
|
70
|
+
// Re-centre on the card's own middle: the centre stays glued to the DOM
|
|
71
|
+
// rect while the edges foreshorten onto the cylinder.
|
|
72
|
+
float bent = uRadius * sin(a) - uRadius * sin(uOffset / uRadius) + uOffset;
|
|
73
|
+
if (uAxis < 0.5) p.x = bent; else p.y = bent;
|
|
74
|
+
p.z = -uRadius * (1.0 - cos(a));
|
|
75
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
const CARD_FRAG = /* glsl */ `
|
|
79
|
+
precision highp float;
|
|
80
|
+
varying vec2 vUv;
|
|
81
|
+
uniform sampler2D uTex;
|
|
82
|
+
uniform vec2 uRes;
|
|
83
|
+
uniform vec2 uTexSize;
|
|
84
|
+
uniform float uCorner;
|
|
85
|
+
|
|
86
|
+
float sdRoundBox(vec2 p, vec2 b, float r) {
|
|
87
|
+
vec2 q = abs(p) - b + r;
|
|
88
|
+
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
void main() {
|
|
92
|
+
vec2 px = (vUv - 0.5) * uRes;
|
|
93
|
+
float d = sdRoundBox(px, uRes * 0.5, uCorner);
|
|
94
|
+
float alpha = 1.0 - smoothstep(-1.0, 1.0, d); // 1px-ish AA on the corner
|
|
95
|
+
if (alpha < 0.003) discard;
|
|
96
|
+
|
|
97
|
+
// object-fit: cover — window the texture around its centre.
|
|
98
|
+
vec2 scale = uRes / max(uTexSize, vec2(1.0));
|
|
99
|
+
vec2 cover = (vUv - 0.5) * (scale / max(scale.x, scale.y)) + 0.5;
|
|
100
|
+
gl_FragColor = vec4(texture2D(uTex, cover).rgb, alpha);
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
/* Floor: one plane lying at the bottom of the stage, lines in world space,
|
|
104
|
+
fading toward the horizon and the sides, drifting slightly with the rail. */
|
|
105
|
+
const GRID_VERT = /* glsl */ `
|
|
106
|
+
varying vec2 vWorld; // world xz under this fragment
|
|
107
|
+
void main() {
|
|
108
|
+
vec4 wp = modelMatrix * vec4(position, 1.0);
|
|
109
|
+
vWorld = wp.xz;
|
|
110
|
+
gl_Position = projectionMatrix * viewMatrix * wp;
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
const GRID_FRAG = /* glsl */ `
|
|
114
|
+
precision highp float;
|
|
115
|
+
varying vec2 vWorld;
|
|
116
|
+
uniform vec2 uShift; // parallax drift with the rail position, px
|
|
117
|
+
uniform vec3 uColor;
|
|
118
|
+
uniform float uOpacity;
|
|
119
|
+
uniform float uSpacing;
|
|
120
|
+
|
|
121
|
+
void main() {
|
|
122
|
+
vec2 cell = (vWorld + uShift) / uSpacing;
|
|
123
|
+
vec2 grad = abs(fract(cell - 0.5) - 0.5) / max(fwidth(cell), 1e-5);
|
|
124
|
+
float line = 1.0 - min(min(grad.x, grad.y), 1.0);
|
|
125
|
+
float depth = smoothstep(-5200.0, -400.0, vWorld.y); // melt into the horizon
|
|
126
|
+
float side = 1.0 - smoothstep(1300.0, 3600.0, abs(vWorld.x));
|
|
127
|
+
gl_FragColor = vec4(uColor, line * uOpacity * depth * side);
|
|
128
|
+
}
|
|
129
|
+
`;
|
|
130
|
+
/** Floor geometry constants — near edge slightly in front of the cards, far
|
|
131
|
+
edge past the horizon; the stage bottom sits where the z=0 plane ends. */
|
|
132
|
+
const GRID_SPAN = 7200;
|
|
133
|
+
const GRID_DEPTH = 6000;
|
|
134
|
+
const GRID_NEAR_Z = 520;
|
|
135
|
+
export function glRail(target, options = {}) {
|
|
136
|
+
initGSAP();
|
|
137
|
+
const track = one(target);
|
|
138
|
+
if (!track)
|
|
139
|
+
return () => { };
|
|
140
|
+
const { viewport, card = ":scope > *", axis = "auto", radius = 1200, corner = 16, grid = true, dpr = 2, lerp, edge, throwScale, wheel, onTick, } = options;
|
|
141
|
+
return guard(options, () => {
|
|
142
|
+
const vp = one(viewport) ?? track.parentElement ?? track;
|
|
143
|
+
/* ---------------- physics first: the rail works with or without a GPU ---------------- */
|
|
144
|
+
let lastPos = 0;
|
|
145
|
+
const stopPhysics = dragRail(track, {
|
|
146
|
+
viewport: vp,
|
|
147
|
+
axis,
|
|
148
|
+
lerp,
|
|
149
|
+
edge,
|
|
150
|
+
throwScale,
|
|
151
|
+
wheel,
|
|
152
|
+
// The outer guard already decided about reduced motion for both of us.
|
|
153
|
+
force: true,
|
|
154
|
+
onTick: (pos, velocity) => {
|
|
155
|
+
lastPos = pos;
|
|
156
|
+
onTick?.(pos, velocity);
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
/* ---------------- availability ladder (silent, no probes) ---------------- */
|
|
160
|
+
if (typeof window === "undefined" || !("WebGLRenderingContext" in window))
|
|
161
|
+
return stopPhysics;
|
|
162
|
+
let renderer;
|
|
163
|
+
try {
|
|
164
|
+
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return stopPhysics; // context refused — the flat DOM rail is the fallback
|
|
168
|
+
}
|
|
169
|
+
/* ---------------- stage + camera ---------------- */
|
|
170
|
+
const prevPosition = vp.style.position;
|
|
171
|
+
if (!prevPosition && getComputedStyle(vp).position === "static") {
|
|
172
|
+
vp.style.position = "relative";
|
|
173
|
+
}
|
|
174
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, dpr));
|
|
175
|
+
const scene = new THREE.Scene();
|
|
176
|
+
const camera = new THREE.PerspectiveCamera(45, 1, 10, 14000);
|
|
177
|
+
// Pixel-space at z = 0: the z=0 plane exactly fills the stage.
|
|
178
|
+
const fitCamera = (w, h) => {
|
|
179
|
+
camera.aspect = w / h;
|
|
180
|
+
camera.position.set(0, 0, h / 2 / Math.tan((camera.fov * Math.PI) / 360));
|
|
181
|
+
camera.updateProjectionMatrix();
|
|
182
|
+
};
|
|
183
|
+
/* ---------------- grid floor ---------------- */
|
|
184
|
+
let gridMesh = null;
|
|
185
|
+
let gridShift = null;
|
|
186
|
+
if (grid) {
|
|
187
|
+
gridShift = new THREE.Vector2();
|
|
188
|
+
const material = new THREE.ShaderMaterial({
|
|
189
|
+
vertexShader: GRID_VERT,
|
|
190
|
+
fragmentShader: GRID_FRAG,
|
|
191
|
+
uniforms: {
|
|
192
|
+
uShift: { value: gridShift },
|
|
193
|
+
uColor: { value: new THREE.Color(0.66, 0.7, 0.78) },
|
|
194
|
+
uOpacity: { value: 0.24 },
|
|
195
|
+
uSpacing: { value: 150 },
|
|
196
|
+
},
|
|
197
|
+
transparent: true,
|
|
198
|
+
depthWrite: false,
|
|
199
|
+
depthTest: false,
|
|
200
|
+
});
|
|
201
|
+
gridMesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material);
|
|
202
|
+
gridMesh.rotation.x = -Math.PI / 2;
|
|
203
|
+
gridMesh.renderOrder = -1; // floor first, cards over it
|
|
204
|
+
scene.add(gridMesh);
|
|
205
|
+
}
|
|
206
|
+
const geometry = new THREE.PlaneGeometry(1, 1, 24, 12);
|
|
207
|
+
const entries = [];
|
|
208
|
+
const loader = new THREE.TextureLoader();
|
|
209
|
+
let disposed = false;
|
|
210
|
+
for (const el of toArray(card, track)) {
|
|
211
|
+
const img = el.querySelector("img");
|
|
212
|
+
const src = img?.currentSrc || img?.src;
|
|
213
|
+
if (!img || !src)
|
|
214
|
+
continue; // label-only card — nothing to paint
|
|
215
|
+
const uniforms = {
|
|
216
|
+
uTex: { value: null },
|
|
217
|
+
uRes: { value: new THREE.Vector2(1, 1) },
|
|
218
|
+
uTexSize: { value: new THREE.Vector2(1, 1) },
|
|
219
|
+
uCorner: { value: corner },
|
|
220
|
+
uSize: { value: new THREE.Vector2(1, 1) },
|
|
221
|
+
uOffset: { value: 0 },
|
|
222
|
+
uRadius: { value: radius },
|
|
223
|
+
uAxis: { value: 0 },
|
|
224
|
+
};
|
|
225
|
+
const material = new THREE.ShaderMaterial({
|
|
226
|
+
vertexShader: CARD_VERT,
|
|
227
|
+
fragmentShader: CARD_FRAG,
|
|
228
|
+
uniforms,
|
|
229
|
+
transparent: true,
|
|
230
|
+
depthWrite: false,
|
|
231
|
+
depthTest: false,
|
|
232
|
+
});
|
|
233
|
+
// Positions come from the shader (uOffset/uSize), not the 1×1 geometry —
|
|
234
|
+
// the default bounding sphere would cull every card off-screen.
|
|
235
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
236
|
+
mesh.frustumCulled = false;
|
|
237
|
+
mesh.visible = false;
|
|
238
|
+
scene.add(mesh);
|
|
239
|
+
const prevOpacity = img.style.opacity;
|
|
240
|
+
entries.push({ el, img, mesh, material, prevOpacity });
|
|
241
|
+
loader.load(src, (texture) => {
|
|
242
|
+
if (disposed) {
|
|
243
|
+
texture.dispose();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
texture.minFilter = THREE.LinearFilter;
|
|
247
|
+
texture.magFilter = THREE.LinearFilter;
|
|
248
|
+
// No sRGB decode: the raw shader passes sampled values through, so
|
|
249
|
+
// the texture stays an ordinary RGBA8 upload (same contract as
|
|
250
|
+
// webglMedia — built-in colourSpace conversion only happens inside
|
|
251
|
+
// three's own material chunks).
|
|
252
|
+
uniforms.uTex.value = texture;
|
|
253
|
+
uniforms.uTexSize.value.set(texture.image?.width || 1, texture.image?.height || 1);
|
|
254
|
+
mesh.visible = true;
|
|
255
|
+
img.style.opacity = "0"; // the canvas owns these pixels from here
|
|
256
|
+
}, undefined, () => {
|
|
257
|
+
/* 404 / decode failure — this card's <img> was never hidden. */
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (!entries.length) {
|
|
261
|
+
// Nothing renderable — plain dragRail is the whole effect.
|
|
262
|
+
geometry.dispose();
|
|
263
|
+
gridMesh?.geometry.dispose();
|
|
264
|
+
gridMesh?.material?.dispose();
|
|
265
|
+
renderer.dispose();
|
|
266
|
+
return stopPhysics;
|
|
267
|
+
}
|
|
268
|
+
/* ---------------- canvas: under the track, over the stage ---------------- */
|
|
269
|
+
const canvas = renderer.domElement;
|
|
270
|
+
canvas.style.cssText =
|
|
271
|
+
"position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none;";
|
|
272
|
+
vp.insertBefore(canvas, track);
|
|
273
|
+
vp.dataset.akGlRail = "true";
|
|
274
|
+
/* ---------------- sizing ---------------- */
|
|
275
|
+
const resize = () => {
|
|
276
|
+
const w = Math.max(1, vp.clientWidth);
|
|
277
|
+
const h = Math.max(1, vp.clientHeight);
|
|
278
|
+
renderer.setSize(w, h, false);
|
|
279
|
+
fitCamera(w, h);
|
|
280
|
+
if (gridMesh) {
|
|
281
|
+
gridMesh.scale.set(GRID_SPAN, GRID_DEPTH, 1);
|
|
282
|
+
// Local +y maps to world −z, so centre the plane to span
|
|
283
|
+
// [GRID_NEAR_Z − GRID_DEPTH, GRID_NEAR_Z] in z.
|
|
284
|
+
gridMesh.position.set(0, -h / 2 + 2, GRID_NEAR_Z - GRID_DEPTH / 2);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
resize();
|
|
288
|
+
let ro = null;
|
|
289
|
+
if (typeof ResizeObserver === "function") {
|
|
290
|
+
ro = new ResizeObserver(resize);
|
|
291
|
+
ro.observe(vp);
|
|
292
|
+
}
|
|
293
|
+
/* ---------------- loop ---------------- */
|
|
294
|
+
let visible = true;
|
|
295
|
+
let io = null;
|
|
296
|
+
if (typeof IntersectionObserver === "function") {
|
|
297
|
+
io = new IntersectionObserver(([entry]) => (visible = entry.isIntersecting), {
|
|
298
|
+
rootMargin: "120px",
|
|
299
|
+
});
|
|
300
|
+
io.observe(vp);
|
|
301
|
+
}
|
|
302
|
+
const sync = () => {
|
|
303
|
+
const stage = vp.getBoundingClientRect();
|
|
304
|
+
const cx = stage.left + stage.width / 2;
|
|
305
|
+
const cy = stage.top + stage.height / 2;
|
|
306
|
+
const vertical = resolveRailAxis(track, vp, axis) === "y";
|
|
307
|
+
for (const entry of entries) {
|
|
308
|
+
const rect = entry.el.getBoundingClientRect();
|
|
309
|
+
const u = entry.material.uniforms;
|
|
310
|
+
u.uOffset.value = vertical
|
|
311
|
+
? cy - (rect.top + rect.height / 2)
|
|
312
|
+
: rect.left + rect.width / 2 - cx;
|
|
313
|
+
u.uSize.value.set(rect.width, rect.height);
|
|
314
|
+
u.uRes.value.set(rect.width, rect.height);
|
|
315
|
+
u.uAxis.value = vertical ? 1 : 0;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const render = () => {
|
|
319
|
+
if (!visible)
|
|
320
|
+
return;
|
|
321
|
+
sync();
|
|
322
|
+
gridShift?.set(lastPos * 0.1, 0); // subtle parallax: the floor trails the rail
|
|
323
|
+
renderer.render(scene, camera);
|
|
324
|
+
};
|
|
325
|
+
gsap.ticker.add(render);
|
|
326
|
+
/* ---------------- teardown ---------------- */
|
|
327
|
+
return () => {
|
|
328
|
+
disposed = true;
|
|
329
|
+
stopPhysics();
|
|
330
|
+
gsap.ticker.remove(render);
|
|
331
|
+
io?.disconnect();
|
|
332
|
+
ro?.disconnect();
|
|
333
|
+
for (const entry of entries) {
|
|
334
|
+
entry.material.uniforms.uTex.value?.dispose();
|
|
335
|
+
entry.material.dispose();
|
|
336
|
+
entry.img.style.opacity = entry.prevOpacity;
|
|
337
|
+
}
|
|
338
|
+
geometry.dispose();
|
|
339
|
+
if (gridMesh) {
|
|
340
|
+
gridMesh.geometry.dispose();
|
|
341
|
+
gridMesh.material.dispose();
|
|
342
|
+
}
|
|
343
|
+
renderer.dispose();
|
|
344
|
+
canvas.remove();
|
|
345
|
+
delete vp.dataset.akGlRail;
|
|
346
|
+
vp.style.position = prevPosition;
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=gl-rail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gl-rail.js","sourceRoot":"","sources":["../../src/three/gl-rail.ts"],"names":[],"mappings":"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"}
|
package/dist/three/index.d.ts
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
* The core barrel (`@cosmictraveler002/anim-kit`) never imports three, so
|
|
7
7
|
* plain DOM/scroll users keep a gsap+lenis-only dependency tree.
|
|
8
8
|
*
|
|
9
|
-
* import { webglMedia } from "@cosmictraveler002/anim-kit/three";
|
|
9
|
+
* import { webglMedia, glRail } from "@cosmictraveler002/anim-kit/three";
|
|
10
10
|
*/
|
|
11
11
|
export { webglMedia } from "./webgl-media.js";
|
|
12
12
|
export type { WebglMediaOptions } from "./webgl-media.js";
|
|
13
|
+
export { glRail } from "./gl-rail.js";
|
|
14
|
+
export type { GlRailOptions } from "./gl-rail.js";
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/three/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/three/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|