pixi-effects 0.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/LICENSE +21 -0
- package/README.md +89 -0
- package/dist/Controller.cjs +940 -0
- package/dist/Controller.cjs.map +1 -0
- package/dist/Controller.d.cts +109 -0
- package/dist/Controller.d.ts +109 -0
- package/dist/Controller.js +933 -0
- package/dist/Controller.js.map +1 -0
- package/dist/Movie-Bp66rkaC.d.cts +364 -0
- package/dist/Movie-Bp66rkaC.d.ts +364 -0
- package/dist/index.cjs +3045 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +79 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +3023 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { Application } from 'pixi.js';
|
|
2
|
+
import { gsap } from 'gsap';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* pixi-effects public DSL types.
|
|
6
|
+
*
|
|
7
|
+
* The composition spec users pass to `Movie.init({ composition })` is
|
|
8
|
+
* shaped by `CompositionSpec`. Every `SequenceSpec` is a discriminated
|
|
9
|
+
* union over `type`, so editor autocomplete narrows correctly.
|
|
10
|
+
*/
|
|
11
|
+
/** A string is treated as an arithmetic expression evaluated against the scope (see src/expr/Parser.ts). */
|
|
12
|
+
type Expr = string;
|
|
13
|
+
/** Any prop value: a number, an Expr string, or any string passed through verbatim (e.g. color hex, font names). */
|
|
14
|
+
type PropValue = number | string;
|
|
15
|
+
/** Generic prop bag (key → value). */
|
|
16
|
+
type Props = Record<string, PropValue>;
|
|
17
|
+
/** A single keyframe entry. Either `set`, `to`, `from`, or `from`+`to` is meaningful per kind. */
|
|
18
|
+
interface Keyframe {
|
|
19
|
+
at?: number;
|
|
20
|
+
duration?: number;
|
|
21
|
+
ease?: string;
|
|
22
|
+
set?: Props;
|
|
23
|
+
to?: Props;
|
|
24
|
+
from?: Props;
|
|
25
|
+
}
|
|
26
|
+
interface AssetSpec {
|
|
27
|
+
name: string;
|
|
28
|
+
src: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Escape hatch for arbitrary PIXI filters (e.g. anything from `pixi-filters`,
|
|
32
|
+
* a custom user-built `Filter` subclass, or a community filter package).
|
|
33
|
+
*
|
|
34
|
+
* The instance is used as-is; animation paths (`filters.<name>.<prop>`) work
|
|
35
|
+
* as long as the filter has a writable property at that path.
|
|
36
|
+
*
|
|
37
|
+
* Example:
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { GlowFilter } from 'pixi-filters';
|
|
40
|
+
*
|
|
41
|
+
* filters: [
|
|
42
|
+
* { type: 'custom', name: 'glow', filter: new GlowFilter({ outerStrength: 2 }) },
|
|
43
|
+
* ],
|
|
44
|
+
* keyframes: [
|
|
45
|
+
* { at: 1, to: { 'filters.glow.outerStrength': 5 }, duration: 0.5 },
|
|
46
|
+
* ],
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
interface CustomFilterSpec {
|
|
50
|
+
type: 'custom';
|
|
51
|
+
name?: string;
|
|
52
|
+
/** A PIXI `Filter` instance. Imported here as `unknown` to avoid a hard `pixi.js` type dep on consumers reading this file purely as types. */
|
|
53
|
+
filter: unknown;
|
|
54
|
+
}
|
|
55
|
+
interface ChromaKeyFilterSpec {
|
|
56
|
+
type: 'chromaKey';
|
|
57
|
+
name?: string;
|
|
58
|
+
keyColor?: string | [number, number, number];
|
|
59
|
+
threshold?: number;
|
|
60
|
+
smoothing?: number;
|
|
61
|
+
spill?: number;
|
|
62
|
+
}
|
|
63
|
+
type FilterSpec = ChromaKeyFilterSpec | CustomFilterSpec;
|
|
64
|
+
interface TransitionCommon {
|
|
65
|
+
/** Sibling sequence's `name` — the outgoing scene. */
|
|
66
|
+
from: string;
|
|
67
|
+
/** Sibling sequence's `name` — the incoming scene. Must be declared after `from` in the parent's `sequences[]`. */
|
|
68
|
+
to: string;
|
|
69
|
+
/** Start time (parent-relative seconds). Same `at` semantics as Keyframe. */
|
|
70
|
+
at: number;
|
|
71
|
+
/** Length of the transition in seconds. Must be > 0. */
|
|
72
|
+
duration: number;
|
|
73
|
+
/** GSAP easing name. Default `'none'` (linear). */
|
|
74
|
+
ease?: string;
|
|
75
|
+
}
|
|
76
|
+
interface CrossfadeTransition extends TransitionCommon {
|
|
77
|
+
kind: 'crossfade';
|
|
78
|
+
}
|
|
79
|
+
interface WipeTransition extends TransitionCommon {
|
|
80
|
+
kind: 'wipe';
|
|
81
|
+
direction: 'left' | 'right' | 'up' | 'down';
|
|
82
|
+
/** 0..1 edge softness. Default 0.02. */
|
|
83
|
+
smoothing?: number;
|
|
84
|
+
}
|
|
85
|
+
interface IrisTransition extends TransitionCommon {
|
|
86
|
+
kind: 'iris';
|
|
87
|
+
/** `'in'` (default) = B opens up from a point. `'out'` = A closes down to a point. */
|
|
88
|
+
mode?: 'in' | 'out';
|
|
89
|
+
smoothing?: number;
|
|
90
|
+
}
|
|
91
|
+
interface SlideTransition extends TransitionCommon {
|
|
92
|
+
kind: 'slide';
|
|
93
|
+
/** Direction of motion: `'left'` = both sequences slide leftward (B enters from the right). */
|
|
94
|
+
direction: 'left' | 'right' | 'up' | 'down';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* "Dip through": A fades out across the first half of the window, B fades in
|
|
98
|
+
* across the second half. The visible color during the dip is whatever sits
|
|
99
|
+
* behind A and B (canvas background, or any persistent layer beneath them).
|
|
100
|
+
*/
|
|
101
|
+
interface DipTransition extends TransitionCommon {
|
|
102
|
+
kind: 'dip';
|
|
103
|
+
}
|
|
104
|
+
interface ZoomTransition extends TransitionCommon {
|
|
105
|
+
kind: 'zoom';
|
|
106
|
+
/**
|
|
107
|
+
* `'in'` (default): B opens up — starts at `fromScale` and zooms to 1.
|
|
108
|
+
* `'out'`: A closes — zooms from 1 to `fromScale` and fades.
|
|
109
|
+
*/
|
|
110
|
+
mode?: 'in' | 'out';
|
|
111
|
+
/** Starting scale of the zoomed sequence. Default 4 (B starts 4x size). */
|
|
112
|
+
fromScale?: number;
|
|
113
|
+
}
|
|
114
|
+
interface DissolveTransition extends TransitionCommon {
|
|
115
|
+
kind: 'dissolve';
|
|
116
|
+
/** Pattern frequency. Higher = finer grain. Default 30. */
|
|
117
|
+
scale?: number;
|
|
118
|
+
/** Pattern offset for reproducibly varying the dissolve shape. Default 0. */
|
|
119
|
+
seed?: number;
|
|
120
|
+
/** 0..1 edge softness within each chunk. Default 0.05. */
|
|
121
|
+
smoothing?: number;
|
|
122
|
+
}
|
|
123
|
+
type TransitionSpec = CrossfadeTransition | WipeTransition | IrisTransition | SlideTransition | DipTransition | ZoomTransition | DissolveTransition;
|
|
124
|
+
interface SequenceCommon {
|
|
125
|
+
name?: string;
|
|
126
|
+
at?: number;
|
|
127
|
+
duration?: number;
|
|
128
|
+
initial?: Props;
|
|
129
|
+
keyframes?: Keyframe[];
|
|
130
|
+
filters?: FilterSpec[];
|
|
131
|
+
/**
|
|
132
|
+
* Override PIXI's auto-computed filter region. By default, filters apply
|
|
133
|
+
* only inside the target's bounding box. Setting this to a parent-relative
|
|
134
|
+
* rectangle lets a filter (e.g. a wipe / iris transition) draw across an
|
|
135
|
+
* area larger than the sprite — useful when the sprite content is small
|
|
136
|
+
* but the visual effect should cover the whole composition.
|
|
137
|
+
*/
|
|
138
|
+
filterArea?: {
|
|
139
|
+
x: number;
|
|
140
|
+
y: number;
|
|
141
|
+
width: number;
|
|
142
|
+
height: number;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Inline mask spec. The mask sequence is built as a hidden sibling and
|
|
146
|
+
* wired via `target.mask` — it shapes which pixels of this sequence are
|
|
147
|
+
* visible. Mask coordinates live in the same space as this sequence
|
|
148
|
+
* (i.e. relative to the same parent composition).
|
|
149
|
+
*
|
|
150
|
+
* The mask is itself a sequence, so it can have its own `initial` and
|
|
151
|
+
* `keyframes` — useful for reveal animations (a circle growing from
|
|
152
|
+
* `radius: 0` to full-size). It defaults to running for this sequence's
|
|
153
|
+
* full lifetime.
|
|
154
|
+
*
|
|
155
|
+
* Any sequence type works as a mask; shapes are the natural choice for
|
|
156
|
+
* geometric reveals.
|
|
157
|
+
*/
|
|
158
|
+
mask?: SequenceSpec;
|
|
159
|
+
/**
|
|
160
|
+
* When true, the mask is inverted: pixels inside the mask shape become
|
|
161
|
+
* transparent and pixels outside become visible. Useful for "knockout"
|
|
162
|
+
* effects (cut a hole through an image / panel). Default false.
|
|
163
|
+
*
|
|
164
|
+
* Routed through PIXI's native `setMask({ inverse: true })`.
|
|
165
|
+
*/
|
|
166
|
+
maskInverted?: boolean;
|
|
167
|
+
}
|
|
168
|
+
interface VideoSequenceSpec extends SequenceCommon {
|
|
169
|
+
type: 'video';
|
|
170
|
+
asset: string;
|
|
171
|
+
loop?: boolean;
|
|
172
|
+
audio?: boolean;
|
|
173
|
+
volume?: number;
|
|
174
|
+
}
|
|
175
|
+
interface ImageSequenceSpec extends SequenceCommon {
|
|
176
|
+
type: 'image';
|
|
177
|
+
asset: string;
|
|
178
|
+
/**
|
|
179
|
+
* Colour space used to interpolate `tint` keyframes. Default `'rgb'`
|
|
180
|
+
* (linear sRGB lerp via PIXI's tint pipeline). Set to `'oklab'` /
|
|
181
|
+
* `'oklch'` for perceptually uniform interpolation — same semantics
|
|
182
|
+
* as on `shape`.
|
|
183
|
+
*/
|
|
184
|
+
colorSpace?: 'rgb' | 'oklab' | 'oklch';
|
|
185
|
+
}
|
|
186
|
+
interface TextSequenceSpec extends SequenceCommon {
|
|
187
|
+
type: 'text';
|
|
188
|
+
text?: string;
|
|
189
|
+
/** Subset of PIXI v8 TextStyleOptions. String values may be exprs (e.g. fontSize: 'GW * 0.05'). */
|
|
190
|
+
style?: Record<string, PropValue | {
|
|
191
|
+
color?: PropValue;
|
|
192
|
+
width?: PropValue;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Colour space used to interpolate `fill` keyframes. Default `'rgb'`.
|
|
196
|
+
* Set to `'oklab'` / `'oklch'` for perceptually uniform interpolation
|
|
197
|
+
* — same semantics as on `shape`. The text's fill is re-rasterised on
|
|
198
|
+
* every frame the tween is active.
|
|
199
|
+
*/
|
|
200
|
+
colorSpace?: 'rgb' | 'oklab' | 'oklch';
|
|
201
|
+
}
|
|
202
|
+
interface AudioSequenceSpec extends SequenceCommon {
|
|
203
|
+
type: 'audio';
|
|
204
|
+
asset: string;
|
|
205
|
+
loop?: boolean;
|
|
206
|
+
volume?: number;
|
|
207
|
+
}
|
|
208
|
+
interface CompositionSequenceSpec extends SequenceCommon {
|
|
209
|
+
type: 'composition';
|
|
210
|
+
width?: number;
|
|
211
|
+
height?: number;
|
|
212
|
+
sequences?: SequenceSpec[];
|
|
213
|
+
transitions?: TransitionSpec[];
|
|
214
|
+
}
|
|
215
|
+
interface ShapeBase extends SequenceCommon {
|
|
216
|
+
type: 'shape';
|
|
217
|
+
/**
|
|
218
|
+
* Colour space used to interpolate `fillColor` / `strokeColor` keyframes.
|
|
219
|
+
*
|
|
220
|
+
* - `'rgb'` (default): linear RGB tween via `gsap.utils.interpolate`.
|
|
221
|
+
* Fast, but a red → green ramp passes through muddy brown / olive
|
|
222
|
+
* greys at the midpoint because intermediate sRGB values are
|
|
223
|
+
* perceptually unbalanced.
|
|
224
|
+
* - `'oklab'` / `'oklch'`: perceptually uniform colour spaces. Hue and
|
|
225
|
+
* chroma stay vibrant through the transition. `oklch` interpolates
|
|
226
|
+
* hue along the shorter angular path, giving smooth rainbow-like
|
|
227
|
+
* sweeps; `oklab` is straight-line in the chromaticity plane.
|
|
228
|
+
*/
|
|
229
|
+
colorSpace?: 'rgb' | 'oklab' | 'oklch';
|
|
230
|
+
}
|
|
231
|
+
interface RectShapeSpec extends ShapeBase {
|
|
232
|
+
shape: 'rect';
|
|
233
|
+
width: PropValue;
|
|
234
|
+
height: PropValue;
|
|
235
|
+
/** Rounded corner radius. Default 0 (sharp). */
|
|
236
|
+
cornerRadius?: PropValue;
|
|
237
|
+
/**
|
|
238
|
+
* Where the local origin sits relative to the rect's bounding box.
|
|
239
|
+
* `0` = left / top edge, `0.5` = centre (default), `1` = right / bottom
|
|
240
|
+
* edge. Animating `width` with `anchorX: 0` makes the bar grow
|
|
241
|
+
* rightward (progress-bar style) without the left edge drifting.
|
|
242
|
+
*/
|
|
243
|
+
anchorX?: PropValue;
|
|
244
|
+
anchorY?: PropValue;
|
|
245
|
+
}
|
|
246
|
+
interface CircleShapeSpec extends ShapeBase {
|
|
247
|
+
shape: 'circle';
|
|
248
|
+
radius: PropValue;
|
|
249
|
+
/** See RectShapeSpec.anchorX. Default 0.5 (centre). */
|
|
250
|
+
anchorX?: PropValue;
|
|
251
|
+
anchorY?: PropValue;
|
|
252
|
+
}
|
|
253
|
+
interface EllipseShapeSpec extends ShapeBase {
|
|
254
|
+
shape: 'ellipse';
|
|
255
|
+
radiusX: PropValue;
|
|
256
|
+
radiusY: PropValue;
|
|
257
|
+
/** See RectShapeSpec.anchorX. Default 0.5 (centre). */
|
|
258
|
+
anchorX?: PropValue;
|
|
259
|
+
anchorY?: PropValue;
|
|
260
|
+
}
|
|
261
|
+
interface LineShapeSpec extends ShapeBase {
|
|
262
|
+
shape: 'line';
|
|
263
|
+
/** Line endpoints relative to the shape's local origin. */
|
|
264
|
+
from: [PropValue, PropValue];
|
|
265
|
+
to: [PropValue, PropValue];
|
|
266
|
+
}
|
|
267
|
+
interface PolygonShapeSpec extends ShapeBase {
|
|
268
|
+
shape: 'polygon';
|
|
269
|
+
/** Vertices in local space. The path is auto-closed. */
|
|
270
|
+
points: Array<[PropValue, PropValue]>;
|
|
271
|
+
/** When true, draw an open polyline instead of a closed polygon. Default false. */
|
|
272
|
+
open?: boolean;
|
|
273
|
+
}
|
|
274
|
+
interface PathShapeSpec extends ShapeBase {
|
|
275
|
+
shape: 'path';
|
|
276
|
+
/** SVG path data (`d` attribute). Goes through PIXI's GraphicsContext.svg(). */
|
|
277
|
+
d: string;
|
|
278
|
+
}
|
|
279
|
+
type ShapeSequenceSpec = RectShapeSpec | CircleShapeSpec | EllipseShapeSpec | LineShapeSpec | PolygonShapeSpec | PathShapeSpec;
|
|
280
|
+
type SequenceSpec = VideoSequenceSpec | ImageSequenceSpec | TextSequenceSpec | AudioSequenceSpec | CompositionSequenceSpec | ShapeSequenceSpec;
|
|
281
|
+
/** Top-level composition (root node) — same as `CompositionSequenceSpec` minus the discriminant. */
|
|
282
|
+
interface CompositionSpec extends SequenceCommon {
|
|
283
|
+
width?: number;
|
|
284
|
+
height?: number;
|
|
285
|
+
sequences?: SequenceSpec[];
|
|
286
|
+
transitions?: TransitionSpec[];
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
interface MovieOptions {
|
|
290
|
+
width?: number;
|
|
291
|
+
height?: number;
|
|
292
|
+
duration?: number;
|
|
293
|
+
frameRate?: number;
|
|
294
|
+
background?: string;
|
|
295
|
+
canvas?: HTMLCanvasElement;
|
|
296
|
+
assets?: AssetSpec[];
|
|
297
|
+
composition?: CompositionSpec;
|
|
298
|
+
}
|
|
299
|
+
interface RenderOptions {
|
|
300
|
+
format?: 'mp4' | 'mov' | 'webm' | 'mkv';
|
|
301
|
+
video?: {
|
|
302
|
+
codec?: string;
|
|
303
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
304
|
+
};
|
|
305
|
+
audio?: {
|
|
306
|
+
codec?: string;
|
|
307
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
interface FrameEvent {
|
|
311
|
+
frame: number;
|
|
312
|
+
totalFrames: number;
|
|
313
|
+
}
|
|
314
|
+
interface ProgressEvent {
|
|
315
|
+
progress: number;
|
|
316
|
+
frame: number;
|
|
317
|
+
totalFrames: number;
|
|
318
|
+
}
|
|
319
|
+
type Listener = (...args: any[]) => void;
|
|
320
|
+
declare class Movie {
|
|
321
|
+
private _events;
|
|
322
|
+
private _initState;
|
|
323
|
+
app: Application | null;
|
|
324
|
+
timeline: ReturnType<typeof gsap.timeline> | null;
|
|
325
|
+
audioBuffer: AudioBuffer | null;
|
|
326
|
+
audioSource: AudioBufferSourceNode | null;
|
|
327
|
+
gainNode: GainNode | null;
|
|
328
|
+
private _volume;
|
|
329
|
+
private _muted;
|
|
330
|
+
isPlaying: boolean;
|
|
331
|
+
currentFrame: number;
|
|
332
|
+
totalFrames: number;
|
|
333
|
+
width: number;
|
|
334
|
+
height: number;
|
|
335
|
+
duration: number;
|
|
336
|
+
frameRate: number;
|
|
337
|
+
background: string;
|
|
338
|
+
private _audioContext;
|
|
339
|
+
private _rootSequence;
|
|
340
|
+
private _rootContainer;
|
|
341
|
+
private _raf;
|
|
342
|
+
on(event: 'ready', fn: () => void): this;
|
|
343
|
+
on(event: 'frame', fn: (e: FrameEvent) => void): this;
|
|
344
|
+
on(event: 'progress', fn: (e: ProgressEvent) => void): this;
|
|
345
|
+
on(event: 'pause', fn: () => void): this;
|
|
346
|
+
off(event: string, fn: Listener): this;
|
|
347
|
+
emit(event: string, ...args: unknown[]): void;
|
|
348
|
+
get isReady(): boolean;
|
|
349
|
+
private _ensureAudioContext;
|
|
350
|
+
init(options?: MovieOptions): Promise<void>;
|
|
351
|
+
gotoFrame(frame: number, force?: boolean): Promise<void>;
|
|
352
|
+
private _awaitVideoFrames;
|
|
353
|
+
play(): void;
|
|
354
|
+
pause(): void;
|
|
355
|
+
set volume(v: number);
|
|
356
|
+
get volume(): number;
|
|
357
|
+
set muted(v: boolean);
|
|
358
|
+
get muted(): boolean;
|
|
359
|
+
toggleMute(): boolean;
|
|
360
|
+
render(options?: RenderOptions): Promise<Blob>;
|
|
361
|
+
destroy(): Promise<void>;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export { type AssetSpec as A, type ChromaKeyFilterSpec as C, type DipTransition as D, type EllipseShapeSpec as E, type FilterSpec as F, type ImageSequenceSpec as I, type Keyframe as K, type LineShapeSpec as L, Movie as M, type PathShapeSpec as P, type RectShapeSpec as R, type SequenceCommon as S, type TextSequenceSpec as T, type VideoSequenceSpec as V, type WipeTransition as W, type ZoomTransition as Z, type AudioSequenceSpec as a, type CircleShapeSpec as b, type CompositionSequenceSpec as c, type CompositionSpec as d, type CrossfadeTransition as e, type CustomFilterSpec as f, type DissolveTransition as g, type Expr as h, type FrameEvent as i, type IrisTransition as j, type MovieOptions as k, type PolygonShapeSpec as l, type ProgressEvent as m, type PropValue as n, type Props as o, type RenderOptions as p, type SequenceSpec as q, type ShapeSequenceSpec as r, type SlideTransition as s, type TransitionCommon as t, type TransitionSpec as u };
|