@pixerate/flair 0.28.0 → 0.29.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/CHANGELOG.md +13 -0
- package/README.md +48 -6
- package/dist/catalog/index.d.ts +11 -6
- package/dist/catalog/index.js +1 -1
- package/dist/{chunk-4LKAPRFM.js → chunk-6GFOLHCT.js} +920 -34
- package/dist/chunk-6GFOLHCT.js.map +1 -0
- package/dist/{chunk-JL6TI6II.js → chunk-7KYQ4R76.js} +2 -2
- package/dist/chunk-7KYQ4R76.js.map +1 -0
- package/dist/{chunk-STKEKXCK.js → chunk-AUH3PEFW.js} +2 -2
- package/dist/{chunk-PFGGPIMT.js → chunk-DA4UUSDO.js} +58 -3
- package/dist/chunk-DA4UUSDO.js.map +1 -0
- package/dist/{chunk-RDU63CDO.js → chunk-HDYBY3PQ.js} +380 -1
- package/dist/chunk-HDYBY3PQ.js.map +1 -0
- package/dist/{chunk-VLQLRKGW.js → chunk-KZYZX3V5.js} +260 -33
- package/dist/chunk-KZYZX3V5.js.map +1 -0
- package/dist/{chunk-GXP4YLAP.js → chunk-MBKNTXQX.js} +9 -9
- package/dist/chunk-MBKNTXQX.js.map +1 -0
- package/dist/{chunk-H6VDFBIO.js → chunk-SMR2MJXB.js} +156 -5
- package/dist/chunk-SMR2MJXB.js.map +1 -0
- package/dist/{chunk-YBGRXVAE.js → chunk-X3C2VFTM.js} +3 -3
- package/dist/{chunk-CK6EV37I.js → chunk-ZULFHADW.js} +69 -6
- package/dist/chunk-ZULFHADW.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/editor/index.d.ts +3 -3
- package/dist/editor/index.js +3 -3
- package/dist/{effect-GGP66JI6.js → effect-YBWDNIYG.js} +10 -10
- package/dist/embed/index.d.ts +36 -8
- package/dist/embed/index.js +5 -5
- package/dist/{frames-VEcqa40g.d.ts → frames-CGJudAbu.d.ts} +11 -1
- package/dist/index.d.ts +69 -6
- package/dist/index.js +35 -7
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +4 -4
- package/dist/node.js +9 -9
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +7 -7
- package/dist/react/index.js.map +1 -1
- package/dist/{recorder-CDPPTJMG.js → recorder-TYMEZHOT.js} +3 -3
- package/dist/{renderer-teaa98RE.d.ts → renderer-tk1nbVkW.d.ts} +252 -2
- package/dist/svelte/index.d.ts +4 -4
- package/dist/svelte/index.js +7 -7
- package/dist/svelte/index.js.map +1 -1
- package/dist/{svg-BhRboN9q.d.ts → svg-DaKRPA9v.d.ts} +39 -7
- package/dist/{types-DUOMxZaq.d.ts → types-wh28fXW4.d.ts} +2 -2
- package/dist/vector/index.d.ts +2 -2
- package/dist/vector/index.js +5 -3
- package/package.json +1 -1
- package/dist/chunk-4LKAPRFM.js.map +0 -1
- package/dist/chunk-CK6EV37I.js.map +0 -1
- package/dist/chunk-GXP4YLAP.js.map +0 -1
- package/dist/chunk-H6VDFBIO.js.map +0 -1
- package/dist/chunk-JL6TI6II.js.map +0 -1
- package/dist/chunk-PFGGPIMT.js.map +0 -1
- package/dist/chunk-RDU63CDO.js.map +0 -1
- package/dist/chunk-VLQLRKGW.js.map +0 -1
- /package/dist/{chunk-STKEKXCK.js.map → chunk-AUH3PEFW.js.map} +0 -0
- /package/dist/{chunk-YBGRXVAE.js.map → chunk-X3C2VFTM.js.map} +0 -0
- /package/dist/{effect-GGP66JI6.js.map → effect-YBWDNIYG.js.map} +0 -0
- /package/dist/{recorder-CDPPTJMG.js.map → recorder-TYMEZHOT.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @pixerate/flair
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- aae5438: Sound and scrolling as shader inputs, and effects that use them.
|
|
8
|
+
|
|
9
|
+
- New built-ins: `iAudio` (level, bass, mid, treble), `iSpectrum[16]` (64 log-spaced bins), `iBeat` (seconds since the last beat) and `iScroll` (progress through the viewport, page scroll, velocity, scrolling).
|
|
10
|
+
- `ShaderRenderer.setAudioSource(element | stream | node)` listens through a shared `AudioContext` and `AnalyserNode`; `ShaderRenderer.setScrollProgress(p)` pins the scroll for scrubbers. `ShaderFrames.render(t, { audio, scroll })` scripts both.
|
|
11
|
+
- `AudioAnalysis` (pure, deterministic), `analyseAudioBuffer` (offline, frame-exact, with a small radix-2 `fft`), `LiveAudio`, `sharedAudioContext`, `ScrollTracker` and `viewportProgress`.
|
|
12
|
+
- `SvgPlayer` takes `trigger: "scroll"` (scrubbing with the page, over `scrollRange`) and gains `setProgress(p)` and `scrollPosition(p)`.
|
|
13
|
+
- `effectInputs` reports `audio` in `accepts` and `scroll` in `interactions`; `mountEffect` takes an `{ audio }` subject; `recordEffect` takes `audio` (an `AudioBuffer` or a URL) to drive audio-reactive shaders frame for frame and mux the sound as AAC (mp4) or Opus (webm). `standaloneHtml` takes `{ audio: url | "mic" }`.
|
|
14
|
+
- New `audio` category: spectrum-bars, circular-spectrum, waveform-line, bass-pulse, audio-particles, audio-plasma, vinyl. New `scroll` category: scroll-reveal, parallax-layers, scroll-progress-glow, scroll-velocity-blur, scroll-zoom, scroll-draw, scroll-counter, scroll-steps. All play idle demos with no sound or scrolling.
|
|
15
|
+
|
|
3
16
|
## 0.28.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -24,9 +24,11 @@ Flair gives products a library of good-looking, configurable visual effects (her
|
|
|
24
24
|
- Shadertoy-style GLSL ES 3.00 fragment shaders, with controls declared in the source (`// @control`), including image inputs.
|
|
25
25
|
- Compile errors come back with line numbers that match the source.
|
|
26
26
|
- Pointer input beyond Shadertoy's `iMouse`: `iPointer` (position while over the canvas, eased hover amount, seconds held or since release) `iClicks[8]` (the latest clicks' positions and times) and `iTrail[32]` (where the pointer has been over the last second, newest first), so effects answer hovers, presses, taps and moves. `ShaderRenderer` and standalone pages feed them; `ShaderFrames` takes scripted `pointer`, `clicks` and `trail` for recordings.
|
|
27
|
+
- Sound: `iAudio` (level, bass, mid, treble), `iSpectrum[16]` (64 log-spaced bins) and `iBeat` (seconds since the last beat). `ShaderRenderer.setAudioSource` listens to an `<audio>`/`<video>`, a microphone or any Web Audio node; `analyseAudioBuffer` analyses a decoded track offline, so recordings follow it frame for frame (see [Sound and scrolling](#sound-and-scrolling)).
|
|
28
|
+
- Scrolling: `iScroll` (the canvas's progress through the viewport, page scroll, velocity, and whether it is scrolling), fed by `ShaderRenderer` and scriptable in `ShaderFrames`; vector effects scrub with the page under `trigger: "scroll"`.
|
|
27
29
|
- Live previews (`ShaderRenderer`, with optional `{ alpha: true }` for transparent overlays) and many animated or hover-activated thumbnails on one context (`ThumbnailPool`).
|
|
28
30
|
- Frames at exact times (`ShaderFrames`), looping GIFs, and standalone HTML pages.
|
|
29
|
-
- ✒️ **Vector motion (`@pixerate/flair/vector`)**: animated SVG described as data. Catalog vector effects declare their controls in the picture (`{{name: type …}}`), text included. It covers attribute tweens, draw-on strokes, motion along paths, counters (`animateCount` / `formatCount` for DOM elements too), text written letter by letter (`write`, with `scramble` and `caret`), shape morphs between any paths (`morphPaths`, `morphSequence`) and view zooms. Every frame is a pure function of time (`svgFrame`), and `SvgPlayer` plays it (with `scrollTrigger`, `hideWhenPaused`, `reset()`, and `trigger: "hover" | "press" | "click"` to play in answer to the pointer).
|
|
31
|
+
- ✒️ **Vector motion (`@pixerate/flair/vector`)**: animated SVG described as data. Catalog vector effects declare their controls in the picture (`{{name: type …}}`), text included. It covers attribute tweens, draw-on strokes, motion along paths, counters (`animateCount` / `formatCount` for DOM elements too), text written letter by letter (`write`, with `scramble` and `caret`), shape morphs between any paths (`morphPaths`, `morphSequence`) and view zooms. Every frame is a pure function of time (`svgFrame`), and `SvgPlayer` plays it (with `scrollTrigger`, `hideWhenPaused`, `reset()`, and `trigger: "hover" | "press" | "click" | "scroll"` to play in answer to the pointer or scrub with the page).
|
|
30
32
|
- 🎛️ **Effect editor (`@pixerate/flair/editor`)**:
|
|
31
33
|
- A headless editor for an effect's source, values, keyframes, presets and timeline.
|
|
32
34
|
- Built on [`@pixerate/editor`](https://github.com/Pixerate/editor)'s undo history and command registry, with no UI framework assumed.
|
|
@@ -170,10 +172,10 @@ findEffects({ accepts: ["image"], interaction: ["hover"] }); // pictures that re
|
|
|
170
172
|
findEffects({ transparent: true }); // overlays to lay over a page, picture or video
|
|
171
173
|
```
|
|
172
174
|
|
|
173
|
-
- `accepts`: `image` (any picture URL), `video` (a live `<video>`, with `setLiveSource`), `svg` (an SVG URL, drawn with its transparency), `text` (words for a text control, or for a text mask through `textImage("…")`), `mask` (a shape with transparency whose silhouette the effect uses: an icon, a logo, a word), `path` (SVG path data for a shape control).
|
|
175
|
+
- `accepts`: `image` (any picture URL), `video` (a live `<video>`, with `setLiveSource`), `svg` (an SVG URL, drawn with its transparency), `text` (words for a text control, or for a text mask through `textImage("…")`), `mask` (a shape with transparency whose silhouette the effect uses: an icon, a logo, a word), `path` (SVG path data for a shape control), `audio` (sound it reacts to, from reading `iAudio`, `iSpectrum` or `iBeat`).
|
|
174
176
|
- `images`: each image control's name, and whether it `wants` a `picture`, a `mask` or `text`.
|
|
175
177
|
- `texts`: each text control's name, and whether it `holds` `copy`, a `font`, a `path` or `glyphs`.
|
|
176
|
-
- `interactions`: `hover`, `press`, `click`, `trail` (follows where the pointer has been)
|
|
178
|
+
- `interactions`: `hover`, `press`, `click`, `trail` (follows where the pointer has been), `pointer` (follows where it is) or `scroll` (follows the page's scrolling), from the pointer and scroll built-ins a shader reads or a vector effect's `trigger`.
|
|
177
179
|
- `transparent`, `video` and `trigger`, as on the effect.
|
|
178
180
|
|
|
179
181
|
`findEffects` filters on `accepts` (all of them), `interaction` (any of them; `[]` for effects that don't answer the pointer) and `transparent`, and the `catalog.search` command takes the same filters and lists each effect's `accepts` and `interactions`. The `interactive` tag is kept in step with `interactions`.
|
|
@@ -186,6 +188,7 @@ findEffects({ transparent: true }); // overlays to lay over a page, picture or v
|
|
|
186
188
|
- `{ svg }`: an SVG, as markup or a URL.
|
|
187
189
|
- `{ text }`: words, typed into a vector effect, or drawn with `textImage` for a shader's text or mask.
|
|
188
190
|
- `{ path }`: path data.
|
|
191
|
+
- `{ audio }`: sound for an audio-reactive shader: a playing `<audio>` or `<video>` (still heard), a microphone's `MediaStream` (not played back) or a Web Audio node.
|
|
189
192
|
|
|
190
193
|
It puts the subject in the right control (see `effectInputs`) and throws a sentence if the effect can't take it.
|
|
191
194
|
|
|
@@ -197,6 +200,8 @@ mountEffect(el, "crt", { subject: { video: document.querySelector("video")! } })
|
|
|
197
200
|
mountEffect(el, "neon-outline", { subject: { svg: logoMarkup } });
|
|
198
201
|
mountEffect(el, "typewriter", { subject: { text: "Hello there" } });
|
|
199
202
|
mountEffect(el, "transition-wipe", { subject: [{ image: "/a.jpg" }, { image: "/b.jpg" }] });
|
|
203
|
+
mountEffect(el, "spectrum-bars", { subject: { audio: document.querySelector("audio")! } });
|
|
204
|
+
mountEffect(el, "scroll-draw"); // scroll effects follow the page by themselves
|
|
200
205
|
const m = mountEffect(el, "click-ripple"); // overlays get a transparent canvas, interactive effects answer the pointer
|
|
201
206
|
m.setValues({ uSpeed: 2 });
|
|
202
207
|
m.dispose();
|
|
@@ -217,6 +222,7 @@ import { recordEffect } from "@pixerate/flair/embed";
|
|
|
217
222
|
|
|
218
223
|
const mp4 = await recordEffect("image-duotone", { subject: { image: "/team.jpg" }, preset: "Spotify" });
|
|
219
224
|
const webm = await recordEffect("crt", { subject: { video }, format: "webm", duration: 5 });
|
|
225
|
+
const music = await recordEffect("spectrum-bars", { audio: "/song.mp3", duration: 10 }); // the sound drives it and is muxed in
|
|
220
226
|
const gif = await recordEffect("typewriter", { subject: { text: "Hello there" }, format: "gif", width: 640, height: 360, fps: 25 });
|
|
221
227
|
const overlay = await recordEffect("click-ripple", {
|
|
222
228
|
format: "webm",
|
|
@@ -230,7 +236,8 @@ download(mp4); // a Blob
|
|
|
230
236
|
- **Formats.** `mp4` (H.264) or `webm` (VP9, else VP8) are encoded with WebCodecs and written by small built-in muxers: a faststart MP4 (`moov` before `mdat`) and a WebM with no `Cues`. `gif` uses gifenc. `png` gives a ZIP of numbered frames (`frame-0001.png`, …), so every format is one `Blob`. The default is `mp4` where the browser encodes H.264, else `webm`. When the browser can't make a format, it rejects with a sentence that names the formats that would work.
|
|
231
237
|
- **Exact frames.** Frame `i` is drawn at `start + i / fps` off screen, so the result is the same whatever the page is doing. Shaders render with `ShaderFrames`. A `<video>` subject is paused and sought to each frame's time, then put back. A canvas subject is drawn as it is, so draw it for each frame in `beforeFrame(time)`. Vector effects are drawn with `svgView` and rasterised.
|
|
232
238
|
- **Defaults.** 1280 × 720 at 30 fps. The length is a shader's `loop`, or a vector effect's picture plus its `hold`, else 4 s. The bitrate is `width × height × fps × 0.15`. Video sizes round up to even numbers. `recordingPlan(effect, options)` tells you what a recording will be (format, size, frames, encoder) before any frame is drawn.
|
|
233
|
-
- **Interaction.** Shaders that answer the pointer play their idle demo unless `pointer` scripts it, with the same `pointer`, `clicks` and `trail` that `ShaderFrames.render` takes. Click-triggered vector effects take `steps` (ms).
|
|
239
|
+
- **Interaction.** Shaders that answer the pointer play their idle demo unless `pointer` scripts it, with the same `pointer`, `clicks` and `trail` that `ShaderFrames.render` takes. Click-triggered vector effects take `steps` (ms). Scroll effects play their idle demos too.
|
|
240
|
+
- **Sound.** `audio` takes a decoded `AudioBuffer` or an audio file's URL (fetched and decoded at 48 kHz). Audio-reactive shaders follow it frame for frame: each frame's `iAudio`, `iSpectrum` and `iBeat` come from `analyseAudioBuffer` at that frame's time, so the same file always makes the same video. The stretch from `start` to `start + duration` becomes the video's sound track: AAC in an `mp4`, Opus in a `webm` (encoded with WebCodecs' `AudioEncoder`, muxed by the same built-in muxers). Where the browser has no AAC encoder, the default format falls back to `webm`, and an explicit `mp4` is refused with a sentence. Pass `audioTrack: false` for the picture alone. `gif` and `png` have no sound, so there the audio only drives the picture.
|
|
234
241
|
- **Transparency.** `alpha` defaults to the effect's `transparent`. It is kept in `webm` (VP9/VP8 with an alpha channel, encoded as a second stream and stored as `BlockAdditions`, as Chrome does), in `png`, and in `gif` (one see-through colour, so edges are hard). An `mp4` has no alpha, so asking for both is refused. When alpha is off, transparent pixels are laid over `background` (black for shaders, white for vector effects).
|
|
235
242
|
|
|
236
243
|
Limits: video needs WebCodecs (Chrome and Edge 94+, Safari 16.4+ for H.264, and Firefox 130+). Safari doesn't play alpha WebM, so use PNG frames there. Everything is held in memory until the end, so record long or 4K clips in parts. Vector effects are rasterised once per frame, which is slower than shaders. A picture from another site needs CORS, as on screen.
|
|
@@ -355,7 +362,7 @@ const status = renderer.setSource(source); // { ok, errors: [{ line, message }]
|
|
|
355
362
|
parseControls(source); // [{ name: "uTint", type: "vec3", color: true, default: [...] }, ...]
|
|
356
363
|
const gif = await recordGif({ source, width: 480, height: 270, fps: 30, duration: 3 });
|
|
357
364
|
const frames = new ShaderFrames({ source, width: 480, height: 270, alpha: true }); // alpha: keep fragColor.a
|
|
358
|
-
const page = standaloneHtml("My effect", source, { uSpeed: 2 });
|
|
365
|
+
const page = standaloneHtml("My effect", source, { uSpeed: 2 }); // { audio: "song.mp3" } or { audio: "mic" } for sound
|
|
359
366
|
```
|
|
360
367
|
|
|
361
368
|
### 3. Build an editor (any UI)
|
|
@@ -451,6 +458,39 @@ The exporters carry the camera too:
|
|
|
451
458
|
- **FCP7 XML:** a keyframed Distort corner pin on each shot's clip, plus Motion Blur.
|
|
452
459
|
- **EDL:** a `* CAMERA:` note, since CMX 3600 has no transforms.
|
|
453
460
|
|
|
461
|
+
#### Sound and scrolling
|
|
462
|
+
|
|
463
|
+
Two more inputs, beside the pointer, that shaders read as built-ins (declared by the wrapper, so never in a source):
|
|
464
|
+
|
|
465
|
+
| Built-in | What it holds |
|
|
466
|
+
| --- | --- |
|
|
467
|
+
| `vec4 iAudio` | x level (loudness from RMS, 0–1), y bass (20–250 Hz), z mid (250–2000 Hz), w treble (2–16 kHz), each 0–1, smoothed (quick attack, slower release) |
|
|
468
|
+
| `vec4 iSpectrum[16]` | 64 log-spaced frequency bins (about 30 Hz to 16 kHz), 0–1, four to a `vec4`, low to high: bin `i` is `iSpectrum[i / 4][i % 4]` |
|
|
469
|
+
| `float iBeat` | seconds since the last beat (an onset on the bass band over its recent average), -1 before the first |
|
|
470
|
+
| `vec4 iScroll` | x the canvas's progress through the viewport (0 as its top comes in at the bottom, 1 as its bottom leaves at the top), y the page's scroll (0–1), z velocity (viewport heights per second, positive scrolling down, smoothed), w 1 while scrolling, easing back to 0 |
|
|
471
|
+
|
|
472
|
+
With no audio at all every audio uniform is 0, `iBeat` included; with a source connected `iBeat` is -1 or above 0. So an effect can tell silence from "nothing connected". Where nothing scrolls (thumbnails, recordings), `iScroll` is all zero. The catalog's audio and scroll effects play an idle demo then (a synthetic 120 bpm beat, or a page scrolled down and back), which their "Demo" control turns off.
|
|
473
|
+
|
|
474
|
+
```ts
|
|
475
|
+
import { ShaderRenderer, sharedAudioContext, analyseAudioBuffer, ShaderFrames } from "@pixerate/flair";
|
|
476
|
+
|
|
477
|
+
const preview = new ShaderRenderer(host);
|
|
478
|
+
preview.setSource(getEffect("spectrum-bars").source);
|
|
479
|
+
button.onclick = () => preview.setAudioSource(audioElement); // or a mic MediaStream, or any AudioNode; null stops
|
|
480
|
+
preview.setScrollProgress(0.5); // pin iScroll for a scrubber; null follows the page again
|
|
481
|
+
|
|
482
|
+
// Frame-exact, offline: the uniforms at any time of a decoded track.
|
|
483
|
+
const track = analyseAudioBuffer(await sharedAudioContext().decodeAudioData(bytes));
|
|
484
|
+
frames.render(t, { audio: track.at(t), scroll: [0.5, 0.5, 0, 0] });
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
- **Live sound.** `setAudioSource` makes an `AudioContext` (shared by every renderer: `sharedAudioContext()`) and an `AnalyserNode` on first use, and reads them each frame. A media element keeps playing to the speakers through Web Audio (an element can only be wired in once, so the node is reused). A microphone `MediaStream` is listened to, not played. Any `AudioNode` is analysed in its own context. Browsers start an audio context suspended until the page has a click or key press (the autoplay policy). Call `setAudioSource` from a click, or the context resumes on the first one. A media file from another site needs `crossOrigin = "anonymous"` and CORS, or the browser feeds silence. While a source is set, a paused preview still follows the sound. Dispose (or `null`) disconnects it.
|
|
488
|
+
- **The analysis.** `AudioAnalysis` is pure and unit-tested: it turns byte or decibel frequency data (`fftSize / 2` values) into the uniforms with log binning, band averages, attack/release smoothing and beat detection, and the same data at the same times always gives the same result. `analyseAudioBuffer(buffer)` runs it over a decoded track: a Blackman-windowed radix-2 FFT (`fft`, no dependencies) of the samples just before each time, as `AnalyserNode` would hear them, stepped 120 times a second from the start and kept, so frames asked in any order agree.
|
|
489
|
+
- **Scrolling.** `ShaderRenderer` follows the page with passive scroll listeners and `getBoundingClientRect` each frame (only when the shader reads `iScroll`), so a page or a scrolling element moving the canvas both count, and a paused preview still follows. `ScrollTracker` and `viewportProgress` are the pure parts.
|
|
490
|
+
- **Vector effects.** `new SvgPlayer(host, motion, { trigger: "scroll" })` scrubs the picture with its element's progress through the viewport instead of playing it on a clock: from the start at progress 0.1 to the end at 0.6 by default (`scrollRange`), back again as you scroll up. Hosts can drive any player with `player.setProgress(p)` (0–1), which stops a scroll trigger following the page.
|
|
491
|
+
- **Standalone pages.** `standaloneHtml(title, source, values, { audio: "song.mp3" })` adds a looping player in the corner that the page listens to once it plays, and `{ audio: "mic" }` a microphone button. The page itself does not scroll, so scroll effects play their idle demos there.
|
|
492
|
+
- **Thumbnails and the Node exporter.** `ThumbnailPool` and `flair render`/`flair export` declare the built-ins but feed no sound or scroll, so audio and scroll effects show their idle demos.
|
|
493
|
+
|
|
454
494
|
## 🎨 The catalog
|
|
455
495
|
|
|
456
496
|
| Category | Effects |
|
|
@@ -482,6 +522,8 @@ The exporters carry the camera too:
|
|
|
482
522
|
| glow | aura, bloom, pulsing halo, neon outline, backlight glow, rim light, glow ring pulse, glow button |
|
|
483
523
|
| shadow | long shadow, drop shadow lift, light sweep shadows, contact shadow, window shadows, shadow puppets, lift card, exploded layers |
|
|
484
524
|
| distortion | twirl, pinch & bulge, fisheye, mirror tiles, wave warp, ribbed glass, shower glass, datamosh, polar warp, texture displace |
|
|
525
|
+
| audio | spectrum bars, circular spectrum, waveform line, bass pulse, audio particles, audio plasma, vinyl |
|
|
526
|
+
| scroll | scroll reveal, parallax layers, scroll progress glow, scroll velocity blur, scroll zoom, scroll draw, scroll counter, scroll steps |
|
|
485
527
|
| transition | liquid morph, displacement, luma fade, particle swap, ink bleed, pixel dissolve, comic panels, wipe, iris, block dissolve, grid wipe, glass wipe, twister, light leak, cross zoom, whip pan |
|
|
486
528
|
| loader / icon / data | spinner, bouncing dots, pulse ping, equalizer, progress ring, bar chart, line chart, stat counter, route, timeline track, success check, error cross, heartbeat, signature, confetti, flow network, upload card |
|
|
487
529
|
|
|
@@ -514,7 +556,7 @@ npx flair export ./effect.frag -o out.mp4 -w 1280 -h 720 -d 5 --values '{"speed"
|
|
|
514
556
|
|
|
515
557
|
#### Rendering in Node
|
|
516
558
|
|
|
517
|
-
`flair render` and `flair export` render in headless Chrome, so a shader draws exactly as `ShaderRenderer` draws it: the same GLSL wrapper and built-ins (`iPointer`, `iClicks`, `iTrail`), image controls (SVGs sized up first), `int` and `bool` controls. The output format comes from the extension:
|
|
559
|
+
`flair render` and `flair export` render in headless Chrome, so a shader draws exactly as `ShaderRenderer` draws it: the same GLSL wrapper and built-ins (`iPointer`, `iClicks`, `iTrail`, and `iAudio`, `iSpectrum`, `iBeat`, `iScroll`, left at 0 so those effects play their idle demos), image controls (SVGs sized up first), `int` and `bool` controls. The output format comes from the extension:
|
|
518
560
|
|
|
519
561
|
| Output | Notes |
|
|
520
562
|
| --- | --- |
|
package/dist/catalog/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as ControlDef, C as ControlValue } from '../controls-Ec6P0Vpy.js';
|
|
2
|
-
import { a as SvgTrigger } from '../svg-
|
|
3
|
-
import { a as VideoUse, E as EffectDefinition, b as EffectCategory, S as ShaderEffect } from '../types-
|
|
4
|
-
export { C as CURRENT_COLOR, c as EFFECT_CATEGORIES, d as EffectPreset, e as VECTOR_CONTROL_TYPES, f as VIDEO_USES, g as VectorControl, V as VectorEffect, h as colorControl, i as isCurrentColor, n as numberControl, r as renderVectorEffect, v as vectorControlDef, j as vectorControlIssues, k as vectorControls, l as vectorEffectControls } from '../types-
|
|
2
|
+
import { a as SvgTrigger } from '../svg-DaKRPA9v.js';
|
|
3
|
+
import { a as VideoUse, E as EffectDefinition, b as EffectCategory, S as ShaderEffect } from '../types-wh28fXW4.js';
|
|
4
|
+
export { C as CURRENT_COLOR, c as EFFECT_CATEGORIES, d as EffectPreset, e as VECTOR_CONTROL_TYPES, f as VIDEO_USES, g as VectorControl, V as VectorEffect, h as colorControl, i as isCurrentColor, n as numberControl, r as renderVectorEffect, v as vectorControlDef, j as vectorControlIssues, k as vectorControls, l as vectorEffectControls } from '../types-wh28fXW4.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* What an effect takes and how it answers the pointer, worked out from the
|
|
@@ -18,8 +18,11 @@ export { C as CURRENT_COLOR, c as EFFECT_CATEGORIES, d as EffectPreset, e as VEC
|
|
|
18
18
|
* - `text`: words, for a text control, or for a text mask through `textImage`.
|
|
19
19
|
* - `mask`: a shape with transparency (an icon, a logo, `textImage`) whose silhouette the effect uses.
|
|
20
20
|
* - `path`: SVG path data (`d`), for a shape control.
|
|
21
|
+
* - `audio`: sound (a playing `<audio>` or `<video>`, a microphone, a Web
|
|
22
|
+
* Audio node, or an `AudioBuffer` for recordings) that it reacts to
|
|
23
|
+
* through `iAudio`, `iSpectrum` or `iBeat`.
|
|
21
24
|
*/
|
|
22
|
-
type EffectInput = "image" | "video" | "svg" | "text" | "mask" | "path";
|
|
25
|
+
type EffectInput = "image" | "video" | "svg" | "text" | "mask" | "path" | "audio";
|
|
23
26
|
/** Every {@link EffectInput}. */
|
|
24
27
|
declare const EFFECT_INPUTS: readonly EffectInput[];
|
|
25
28
|
/**
|
|
@@ -29,8 +32,10 @@ declare const EFFECT_INPUTS: readonly EffectInput[];
|
|
|
29
32
|
* - `click`: answers each click or tap.
|
|
30
33
|
* - `trail`: follows where the pointer has just been.
|
|
31
34
|
* - `pointer`: follows where the pointer is.
|
|
35
|
+
* - `scroll`: follows the page's scrolling (`iScroll`, or a vector effect's
|
|
36
|
+
* `trigger: "scroll"`).
|
|
32
37
|
*/
|
|
33
|
-
type EffectInteraction = "hover" | "press" | "click" | "trail" | "pointer";
|
|
38
|
+
type EffectInteraction = "hover" | "press" | "click" | "trail" | "pointer" | "scroll";
|
|
34
39
|
/** Every {@link EffectInteraction}. */
|
|
35
40
|
declare const EFFECT_INTERACTIONS: readonly EffectInteraction[];
|
|
36
41
|
/** A shader's image control and what it wants. */
|
|
@@ -159,7 +164,7 @@ declare function getEffect(id: string): EffectDefinition | undefined;
|
|
|
159
164
|
* (`accepts`: image, video, svg, text, mask, path), its image controls and
|
|
160
165
|
* whether each wants a picture, a mask or text, its text controls (copy,
|
|
161
166
|
* font, path, glyphs), how it suits video, how it answers the pointer
|
|
162
|
-
* (`interactions`: hover, press, click, trail, pointer) and whether it draws
|
|
167
|
+
* (`interactions`: hover, press, click, trail, pointer, scroll) and whether it draws
|
|
163
168
|
* over other content. Worked out from the effect itself, so it always agrees
|
|
164
169
|
* with its controls and source.
|
|
165
170
|
*/
|
package/dist/catalog/index.js
CHANGED