pixi-effects 0.47.3 → 0.47.4
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 +10 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/dist/Composition-HTHQ2RLF.js +7 -0
- package/dist/{Composition-6TXRN65C.js.map → Composition-HTHQ2RLF.js.map} +1 -1
- package/dist/Composition-ZYRDRLYB.cjs +16 -0
- package/dist/{Composition-IC274CKO.cjs.map → Composition-ZYRDRLYB.cjs.map} +1 -1
- package/dist/Controller.cjs +3 -3
- package/dist/Controller.js +1 -1
- package/dist/{Spans-M5KMHT6K.cjs → Spans-I7P7ZVZO.cjs} +12 -12
- package/dist/{Spans-M5KMHT6K.cjs.map → Spans-I7P7ZVZO.cjs.map} +1 -1
- package/dist/{Spans-3T6ZEEN4.js → Spans-JYCTJV4V.js} +7 -7
- package/dist/{Spans-3T6ZEEN4.js.map → Spans-JYCTJV4V.js.map} +1 -1
- package/dist/{blendModes-S72MBYKY.js → blendModes-535EMYGK.js} +5 -5
- package/dist/{blendModes-S72MBYKY.js.map → blendModes-535EMYGK.js.map} +1 -1
- package/dist/{blendModes-Y56QAMC4.cjs → blendModes-V5XHC7U4.cjs} +6 -6
- package/dist/{blendModes-Y56QAMC4.cjs.map → blendModes-V5XHC7U4.cjs.map} +1 -1
- package/dist/{chunk-HGKXEPDJ.js → chunk-34YNRCMT.js} +15 -8
- package/dist/chunk-34YNRCMT.js.map +1 -0
- package/dist/{chunk-VTGJRKW4.cjs → chunk-AES2L75M.cjs} +92 -92
- package/dist/{chunk-VTGJRKW4.cjs.map → chunk-AES2L75M.cjs.map} +1 -1
- package/dist/{chunk-JVO2W77G.js → chunk-BFRWSV3R.js} +3 -3
- package/dist/{chunk-JVO2W77G.js.map → chunk-BFRWSV3R.js.map} +1 -1
- package/dist/{chunk-33OVRSXF.cjs → chunk-CJS2S5XU.cjs} +50 -43
- package/dist/chunk-CJS2S5XU.cjs.map +1 -0
- package/dist/{chunk-TWZNOUM7.cjs → chunk-DOLTCXCL.cjs} +7 -2
- package/dist/chunk-DOLTCXCL.cjs.map +1 -0
- package/dist/{chunk-GDY56V74.cjs → chunk-DS2EWRV4.cjs} +96 -96
- package/dist/{chunk-GDY56V74.cjs.map → chunk-DS2EWRV4.cjs.map} +1 -1
- package/dist/{chunk-PC7DFDCV.js → chunk-JBDBICS2.js} +5 -5
- package/dist/{chunk-PC7DFDCV.js.map → chunk-JBDBICS2.js.map} +1 -1
- package/dist/{chunk-6LA7W362.js → chunk-NCM2WU7R.js} +10 -10
- package/dist/{chunk-6LA7W362.js.map → chunk-NCM2WU7R.js.map} +1 -1
- package/dist/{chunk-YSTOH5PC.cjs → chunk-NGJXVJB7.cjs} +6 -6
- package/dist/{chunk-YSTOH5PC.cjs.map → chunk-NGJXVJB7.cjs.map} +1 -1
- package/dist/{chunk-HX73PCVU.js → chunk-RTZ5MW3E.js} +6 -6
- package/dist/{chunk-HX73PCVU.js.map → chunk-RTZ5MW3E.js.map} +1 -1
- package/dist/{chunk-BXOCEZ4U.js → chunk-WGRWFQOB.js} +7 -2
- package/dist/chunk-WGRWFQOB.js.map +1 -0
- package/dist/{chunk-RU4N3B5B.cjs → chunk-WYR2AU4W.cjs} +7 -7
- package/dist/{chunk-RU4N3B5B.cjs.map → chunk-WYR2AU4W.cjs.map} +1 -1
- package/dist/index.cjs +37 -37
- package/dist/index.js +6 -6
- package/dist/loader.css +1 -1
- package/dist/{music-JKOM5YK6.js → music-P4JRT73P.js} +3 -3
- package/dist/{music-JKOM5YK6.js.map → music-P4JRT73P.js.map} +1 -1
- package/dist/{music-6WFTPVHU.cjs → music-XQEPBIDT.cjs} +7 -7
- package/dist/{music-6WFTPVHU.cjs.map → music-XQEPBIDT.cjs.map} +1 -1
- package/dist/present.cjs +13 -13
- package/dist/present.js +6 -6
- package/dist/{sfx-2O6UQEUP.cjs → sfx-G2XAMD7K.cjs} +8 -8
- package/dist/{sfx-2O6UQEUP.cjs.map → sfx-G2XAMD7K.cjs.map} +1 -1
- package/dist/{sfx-VUKARHDX.js → sfx-Z7OQIKHG.js} +3 -3
- package/dist/{sfx-VUKARHDX.js.map → sfx-Z7OQIKHG.js.map} +1 -1
- package/dist/three.cjs +7 -7
- package/dist/three.js +3 -3
- package/docs/api.md +2 -2
- package/docs/dsl.md +5 -4
- package/llms-full.txt +10 -9
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/reference/cheatsheet.md +2 -2
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Composition-6TXRN65C.js +0 -7
- package/dist/Composition-IC274CKO.cjs +0 -16
- package/dist/chunk-33OVRSXF.cjs.map +0 -1
- package/dist/chunk-BXOCEZ4U.js.map +0 -1
- package/dist/chunk-HGKXEPDJ.js.map +0 -1
- package/dist/chunk-TWZNOUM7.cjs.map +0 -1
package/dist/three.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
5
|
-
require('./chunk-
|
|
3
|
+
var chunkCJS2S5XU_cjs = require('./chunk-CJS2S5XU.cjs');
|
|
4
|
+
require('./chunk-NGJXVJB7.cjs');
|
|
5
|
+
require('./chunk-DOLTCXCL.cjs');
|
|
6
6
|
var pixi_js = require('pixi.js');
|
|
7
7
|
var three$1 = require('three');
|
|
8
8
|
|
|
@@ -170,7 +170,7 @@ function releaseThree(kind) {
|
|
|
170
170
|
|
|
171
171
|
// src/three/ThreeSequence.ts
|
|
172
172
|
var NOT_PURE = /\bMath\s*\.\s*random\s*\(|\bDate\s*\.\s*now\s*\(|\bperformance\s*\.\s*now\s*\(|\bnew\s+Date\s*\(/;
|
|
173
|
-
var ThreeSequence = class extends
|
|
173
|
+
var ThreeSequence = class extends chunkCJS2S5XU_cjs.Sequence {
|
|
174
174
|
_renderer = null;
|
|
175
175
|
/** The renderer this layer draws with (`'webgl'` or `'webgpu'`), once it is built. */
|
|
176
176
|
renderer = null;
|
|
@@ -231,7 +231,7 @@ var ThreeSequence = class extends chunk33OVRSXF_cjs.Sequence {
|
|
|
231
231
|
if (typeof spec.update === "function" && NOT_PURE.test(spec.update.toString())) {
|
|
232
232
|
console.warn(`pixi-effects: three layer${spec.name ? ` "${spec.name}"` : ""}: update calls Math.random, Date.now, performance.now or new Date, so it is not deterministic: the same frame would draw differently in playback, in a seek and in an export. Derive the value from t`);
|
|
233
233
|
}
|
|
234
|
-
const scope =
|
|
234
|
+
const scope = chunkCJS2S5XU_cjs.buildScope(this, this.parent, this.root);
|
|
235
235
|
const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;
|
|
236
236
|
const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;
|
|
237
237
|
const resolution = spec.resolution ?? 1;
|
|
@@ -800,7 +800,7 @@ var ThreeSequence = class extends chunk33OVRSXF_cjs.Sequence {
|
|
|
800
800
|
function resolveDim(v, scope) {
|
|
801
801
|
if (v === void 0) return void 0;
|
|
802
802
|
if (typeof v === "number") return v;
|
|
803
|
-
return
|
|
803
|
+
return chunkCJS2S5XU_cjs.evaluateExpr(v, scope);
|
|
804
804
|
}
|
|
805
805
|
var ids = /* @__PURE__ */ new WeakMap();
|
|
806
806
|
var lastId = 0;
|
|
@@ -1093,7 +1093,7 @@ function registerThree(options = {}) {
|
|
|
1093
1093
|
const kind = options.renderer ?? "webgl";
|
|
1094
1094
|
checkRendererKind(kind, "registerThree's renderer");
|
|
1095
1095
|
setPageRenderer(kind);
|
|
1096
|
-
|
|
1096
|
+
chunkCJS2S5XU_cjs.registerSequenceType("three", ThreeSequence);
|
|
1097
1097
|
}
|
|
1098
1098
|
function three(spec) {
|
|
1099
1099
|
return spec;
|
package/dist/three.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-34YNRCMT.js';
|
|
2
|
+
import './chunk-BFRWSV3R.js';
|
|
3
|
+
import './chunk-WGRWFQOB.js';
|
|
4
4
|
import { Texture, Sprite, TextureSource, RenderTexture, Matrix } from 'pixi.js';
|
|
5
5
|
import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, Vector3, Quaternion, Plane, Box3, RenderTarget, Group, AnimationMixer, LoopOnce, LoopRepeat, AmbientLight, DirectionalLight, SpotLight, PointLight, Color, SRGBColorSpace, Fog } from 'three';
|
|
6
6
|
|
package/docs/api.md
CHANGED
|
@@ -237,9 +237,9 @@ interface SoundReport {
|
|
|
237
237
|
duration: number; sampleRate: number; channels: number;
|
|
238
238
|
peakDb: number; // the loudest sample, dBFS
|
|
239
239
|
loudness: { integratedLufs: number | null; // ITU-R BS.1770; null for a sound under 0.4 s or with nothing above −70 LUFS
|
|
240
|
-
truePeakDb: number; clippedSamples: number; silences: Array<{ from: number; to: number }> };
|
|
240
|
+
truePeakDb: number; clippedSamples: number; silences: Array<{ from: number; to: number }> }; // runs of 1 s or more where every channel stays below −60 dBFS, in seconds
|
|
241
241
|
windows: Array<{ t: number; rmsDb: number }>; // the level over time
|
|
242
|
-
notes: string[]; // quiet or loud for web video, little headroom, silent stretches
|
|
242
|
+
notes: string[]; // quiet or loud for web video, little headroom, silent stretches (`the mix is silent from X s to Y s (N s)`, at most 3, then `and N more silent stretch(es)`)
|
|
243
243
|
}
|
|
244
244
|
```
|
|
245
245
|
|
package/docs/dsl.md
CHANGED
|
@@ -63,7 +63,7 @@ interface SequenceCommon {
|
|
|
63
63
|
| `text`, `image`, `video` | the **top-left** corner | `anchorX` / `anchorY: 0.5` to centre |
|
|
64
64
|
| `composition` | its top-left corner | `pivotX` / `pivotY` = the point that sits at `x, y` and that rotation / scale turn about |
|
|
65
65
|
|
|
66
|
-
Shape geometry (`width height radius anchorX …`) may be written at the top level or in `initial`; the top level wins. `rotation`, `skew*` and `rotationX/Y` are in **degrees
|
|
66
|
+
Shape geometry (`width height radius anchorX …`) may be written at the top level or in `initial`; the top level wins. `rotation`, `skew*` and `rotationX/Y` are in **degrees**; a positive `rotation` turns **clockwise** on the screen (+x toward +y, like CSS `rotate()`), about the anchor (a composition: about `pivotX` / `pivotY`, scale first and then rotation). **`skewX` / `skewY` are PixiJS's, not CSS's shear:** they turn an axis about the layer's anchor (the anchored point stays), so `skewX: 40` tilts the layer's vertical edges by 40° and shortens them to `cos 40°` of their length (a CSS `skewX(40deg)` or After Effects' skew keeps the height and moves the bottom by `h · tan 40°`). A point (x, y) of the layer, measured from its anchor, lands at `(x cos β + y sin α, x sin β + y cos α)` for `skewX: α`, `skewY: β`. Pinned by `tests/films/geometry-skew`.
|
|
67
67
|
|
|
68
68
|
A layer is **not removed** when its lifespan `[at, at + duration)` ends: it is only hidden, and it keeps its last animated values. Outside the lifespan it is invisible. **z-order is array order** (later = on top). Build scenes by giving layers `at` / `duration` and stacking them; a full-screen background rect in each scene hides what is below it.
|
|
69
69
|
|
|
@@ -370,7 +370,7 @@ Every primitive draws centred on its local origin (so `anchorX`/`anchorY` and `p
|
|
|
370
370
|
keyframes: [{ at: 0, to: { trimEnd: 1 }, duration: 1, ease: 'power2.inOut' }] } // a check mark drawing itself
|
|
371
371
|
```
|
|
372
372
|
|
|
373
|
-
**Morph (`morphTo` / `morph`).** (Two outlines with the **same number of corners
|
|
373
|
+
**Morph (`morphTo` / `morph`).** (Two outlines with the **same number of corners** (the points of the outline as written: a line back to the start before `Z` is not a corner, but an extra point on an edge IS one), such as two quads, are paired corner to corner, the start of each outline lined up with the nearest of the other's, so every in-between picture is a straight-edged quad and no corner is rounded; `morphPoints` only matters when the corner counts differ or the outlines are curves.) A `path` can turn into another outline: give `morphTo` (SVG path data in the same canvas coordinates as `d`) and animate `morph` from 0 (the `d` outline) to 1 (the `morphTo` outline). In between it is drawn as a polygon of points half way from one to the other (`morphPoints`: 8–2048, default 128). Closed outlines are lined up (start point and direction) so they do not twist; sub-paths are paired in order, and an extra one grows from (or shrinks into) its own centre. Fill and stroke both follow, and `trimStart` / `trimEnd` walk the morphing outline. Write both outlines as `M … L … C … Z` in absolute coordinates (arcs and holes work too, but keep the same number of sub-paths on both sides).
|
|
374
374
|
|
|
375
375
|
```ts
|
|
376
376
|
{ type: 'shape', shape: 'path', d: 'M 640 160 C 780 160 860 260 860 360 C 860 470 770 560 640 560 C 510 560 420 470 420 360 C 420 250 500 160 640 160 Z',
|
|
@@ -561,7 +561,7 @@ Place any 2D layer in depth and view it through a camera — After Effects style
|
|
|
561
561
|
|
|
562
562
|
| Thing | Convention |
|
|
563
563
|
|---|---|
|
|
564
|
-
| Axes | `+x` right, `+y` down, **`+z` toward the viewer** (like CSS `translateZ`). Bigger `z` = nearer = larger on screen. |
|
|
564
|
+
| Axes | `+x` right, `+y` down, **`+z` toward the viewer** (like CSS `translateZ`). Bigger `z` = nearer = larger on screen: a flat layer at `z` is drawn `camZ / (camZ − z)` times its size, `camZ` being the camera's distance from the picture plane (about 989 for 720p at fov 40: `z = −989` is half size, `z = +495` is twice). A layer at or behind the camera plane (`z ≥ camZ`) is hidden for that frame and says so once: `layer "card" is at or behind the camera plane (z = 1000) and is hidden`. |
|
|
565
565
|
| Units | Positions in composition pixels. **Rotations in degrees.** |
|
|
566
566
|
| Rotation signs | Same as CSS: `rotationY: 30` swings the right edge away; `rotationX: 30` brings the bottom edge toward you; `rotation` is the Z axis. |
|
|
567
567
|
| Rotation centre | The same point 2D `rotation` uses: `anchorX/anchorY` (sprites, text, shapes) or `pivotX/pivotY` (compositions). Set `anchorX: 0.5, anchorY: 0.5` to spin about the centre. |
|
|
@@ -798,6 +798,7 @@ The layer's own three.js renderer is `WebGLRenderer` unless you ask for `rendere
|
|
|
798
798
|
- Materials that rewrite three's shaders (`onBeforeCompile`, `ShaderMaterial`, `RawShaderMaterial`) do not run on the WebGPU renderer: a layer that chose `renderer: 'webgpu'` stops building, naming the material and the fix (`renderer: 'webgl'`), instead of drawing a picture that is wrong without saying so. Only what `ctx.scene` holds is looked at: a `ShaderMaterial` kept in a scene of your own and drawn through `ctx.renderer` (a post-processing quad) is not found; three then logs `Material "ShaderMaterial" is not compatible` on every render. The built-in `Mesh*Material`s, `InstancedMesh` and `Points` do run.
|
|
799
799
|
- **Lights follow the time.** Three's WebGPU renderer updates its light uniforms (and its `time`) once per animation-loop frame, so renders that follow each other in one task (a seek, an export) would all show the same lights and a lamp keyframed with `three.lamp.intensity` would not move. The layer therefore advances three's node frame before each render and gives its `time` the layer's own time (this reaches into a private field of three's renderer: a three that no longer has it makes the layer warn once).
|
|
800
800
|
- Measured on one Apple (Metal) machine, headless Chrome, 2026-10-15: the same lit box drew with a mean difference of 0.04–0.06 (of 255) per channel from the WebGL picture (only edge pixels differ). On the repository's own pages the WebGPU picture equals the WebGL one except where a material used `onBeforeCompile` (`three-product-spin`: the floor reflection no longer fades) and where the scene has fog or a hot, thin edge: see "Where the two renderers differ on purpose". The render alone, waiting for the GPU, took about 0.8–0.9 ms either way for a box; for 2,880 instanced rods under two point lights it took about 0.9–1.2 ms on WebGPU against 1.7–2.1 ms on WebGL (1280×720 to 1920×1080). A 90-frame MP4 export took the same time with either (about 22 frames per second: the encode, not three, was the limit).
|
|
801
|
+
- **2D layers on the two backends** (measured by `tests/films/backends-agree` on the same machine, 2026-10-20: shapes, text, a linear gradient, multiply, alpha, rotation, a blur filter): the mean difference per channel is 0.016–0.021 of 255. Away from edges the pictures are equal (text, gradient, blur and multiply: 0); the only differences are the antialiasing of curved and rotated edges, up to 34/255 on one pixel at alpha 0.6. Another GPU may differ by a little more.
|
|
801
802
|
|
|
802
803
|
#### Where the two renderers differ on purpose
|
|
803
804
|
|
|
@@ -1095,7 +1096,7 @@ interface Keyframe {
|
|
|
1095
1096
|
The four kinds are mutually exclusive per keyframe:
|
|
1096
1097
|
|
|
1097
1098
|
- **`set`** — instantaneous property assignment at `at`.
|
|
1098
|
-
- **`to`** — tween from whatever the property is at `at` to the given values, over `duration`.
|
|
1099
|
+
- **`to`** — tween from whatever the property is at `at` to the given values, over `duration`. **Keyframes on one property run in the order of their `at`, not of the list** (written backwards they play the same). A `to` starts from where the keyframe before it ENDED, so two keyframes of one property that overlap in time make the picture jump: the later one takes over at its `at`, starting from the earlier one's end value (A: x 40 → 160 over 0.5–1.5 s, B: → 280 from 1 s: the layer is at 96 just before 1 s and at 160 just after). Start the second after the first ends. Pinned by `tests/films/time-keyframe-order`.
|
|
1099
1100
|
- **`from`** — tween from the given values back to the current property, over `duration`.
|
|
1100
1101
|
- **`from` + `to`** — full fromTo tween, with explicit start and end values.
|
|
1101
1102
|
|
package/llms-full.txt
CHANGED
|
@@ -6,7 +6,7 @@ Concatenation of the skill, cheatsheet, pitfalls, recipes and the DSL / API / me
|
|
|
6
6
|
|
|
7
7
|
<!-- ===== skills/pixi-effects/SKILL.md ===== -->
|
|
8
8
|
|
|
9
|
-
> Written for pixi-effects 0.47.
|
|
9
|
+
> Written for pixi-effects 0.47.4. Update this skill with `npx skills update`; the newest docs are at https://yjmtmtk.github.io/pixi-effects/
|
|
10
10
|
|
|
11
11
|
# pixi-effects — write a video as data
|
|
12
12
|
|
|
@@ -168,7 +168,7 @@ threeD: true // opt into 2.5D (see below)
|
|
|
168
168
|
blendMode: 'normal' | 'add' | 'screen' | 'multiply' | 'overlay' | 'soft-light' | 'hard-light' | 'color-dodge' | 'color-burn' | 'darken' | 'lighten' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'linear-burn' // CSS names (hyphenated); blends with EVERYTHING BELOW the layer; add / screen brighten (glows), multiply darkens, soft-light / overlay for colour casts and contrast, color-dodge for light sources; on a composition the children each blend (to blend it as one picture: threeD: true or a filter); the 14 new ones cost ~2 ms a layer on WebGL (10+ on screen warns)
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
Animatable props (`initial` / keyframes): `x y alpha rotation scale scaleX scaleY pivotX pivotY anchorX anchorY skewX skewY tint width height visible autoAlpha
|
|
171
|
+
Animatable props (`initial` / keyframes): `x y alpha rotation scale scaleX scaleY pivotX pivotY anchorX anchorY skewX skewY tint width height visible autoAlpha` (and PixiJS's own shorthands `position positionX positionY anchor pivot skew tilePosition* tileScale*`), plus for shapes their style/geometry, for text `fill`, for audio `volume`, for 3D `z rotationX rotationY`, filter params as `'filters.<name>.<param>'`, three objects as `'three.<obj>.<path>'`. A mistyped property in `initial` or a keyframe says `layer "x": "alhpa" is not an animatable property — did you mean "alpha"? (in initial, set, to or from)` (once per layer however often it is written); a mistyped text style key says `layer "t": style.fontsize is not a text style key — did you mean "fontSize"? (it is ignored). Keys: …` and lists the valid keys (`style.colour` / `style.color` mean `fill`). **These go in `initial` / keyframes, never at the top level of a shape or text layer** (top-level `x`, `rotation`, `strokeColor`, `fillAlpha` each warn `layer "dot": "x" is a property, not a rect shape key, so it is ignored: write it in initial (initial: { x: 40 }) or in a keyframe`; every warning of this kind names the layer, or says "unnamed <type> layer"): the top level of a shape holds its geometry (`width height radius d startAngle endAngle cornerRadius anchorX anchorY`), `trimStart` / `trimEnd`, `strokeCap` / `strokeJoin`, `fillGradient`.
|
|
172
172
|
|
|
173
173
|
Keyframe kinds: `set` (jump at `at`; undone when you seek back), `to` (animate to), `from` (animate from), `from`+`to`; a value may be relative to where the layer stands (`from: { x: '-=36' }` slides in from 36 px to the left of its place). `from` / `from+to` show their start value from the layer's start, so a delayed fade-in needs no `initial.alpha`. `repeat` (finite extra plays), `yoyo`, `repeatDelay` loop any of them (endless repeats are not allowed: `repeat: -1` (the GSAP habit) is refused with a warning, write a count that covers the layer, `repeat: 40`; a `from` keyframe with a later `at` puts its start value on the layer from frame 0, the layer does not wait for the `at`). `ease` = an ease name (`'none'`, `'power2.out'`, `'expo.out'`, `'back.out(1.7)'`, `'elastic.out(1,0.5)'`, `'sine.inOut'`, `'bounce.out'`, **`'cubic-bezier(.4, 0, .2, 1)'`** (CSS syntax, x1 and x2 in 0…1; `.4, 0, .2, 1` is a gentle in-out; `.2, .8, .2, 1` is FRONT-LOADED, not slow motion: half of the change in the first 13 % of the time, 90 % by 39 %, 99 % by 74 %, then a long settle, so what sits at the END of the content gets the glide; `.2, .8, .5, 1` has a shorter tail). `power1…4` are the powers 2…5: `power2` is a cubic, `power2.in` has done only 12.5 % at half time (42 % at three quarters)… and springs: `'spring(mass, stiffness, damping)'` or `'spring.gentle' | 'snappy' | 'bouncy' | 'wobbly' | 'slow'`; **`duration: 'auto'` = the time the spring takes to settle** (presets, settle time / highest value reached as a multiple of the target: `snappy` 0.42 s / 1.01, `gentle` 0.72 s / 1.02, `bouncy` 1.08 s / 1.28, `slow` 1.29 s / 1.00, `wobbly` 1.61 s / 1.40: time the next beat from these) (real physics; with a number `duration` is the settle time and only the damping ratio shapes it; a damping ratio of 1 or more never overshoots, so `spring(1,170,26)` does not bounce: use damping below 20 at stiffness 170; `'auto'` works on keyframes only, not in `animateText` / `orbit` tweens; a `stagger` ease may be a spring, its delays are held inside the spread). Default ease is linear.
|
|
174
174
|
|
|
@@ -176,7 +176,7 @@ Keyframe kinds: `set` (jump at `at`; undone when you seek back), `to` (animate t
|
|
|
176
176
|
|
|
177
177
|
**text** — `text`, `resolution` (1–8: draw at N× the pixels so text inside a parent scaled up N× stays sharp), `style` (any PixiJS TextStyle field: `fontSize fontFamily fontWeight fill letterSpacing lineHeight align wordWrap wordWrapWidth stroke dropShadow padding`; expressions OK for numbers), `colorSpace`. Default anchor is **top-left**; use `anchorX/anchorY: 0.5` to centre on `x,y`. A text layer has one animatable number, `value`, printed where the text contains `{value}` (`text: '{value} users'`, `initial: { value: 0 }`, keyframe `to: { value: 2480 }`; `format: { decimals, grouping, pad /* zero-pad the whole part: pad 2 → 05 */, time: 'hh:mm:ss'|'h:mm:ss'|'hh:mm'|'mm:ss'|'m:ss' /* the value in SECONDS as a clock */ }`) — that is how counters work. **Changing text:** a keyframe `set: { text: 'Two' }` swaps the string at that time (undone on seek back; `to` / `from` cannot tween a string); `visibleChars` (number, first N characters; starts at 0 once animated) is a typewriter: `to: { visibleChars: 30 }, duration: 2.4, ease: 'none'` — use `anchorX: 0` + `style.align: 'left'` so it grows rightward. Multi-line text is centre-aligned by default (`style.align: 'left'` to change). **Colour inside one line:** `spans: [{ text: 'type', fill: '#7fa07f' }, ': ', { text: "'a'", fill: '#ffd166', fontWeight: '700' }, ',\n next line']` instead of `text` (strings use the layer's `style`; a span changes only fill / fontWeight / fontStyle / fontVariant / letterSpacing / dropShadow, never a size, font or stroke (those are the layer's `style`); `\n` starts a line; `style.align: 'left'` for code; `visibleChars` types over all the spans; it becomes a group of text layers `<name>.0…`).
|
|
178
178
|
|
|
179
|
-
**image** — `asset`, `tint`, `colorSpace: 'rgb'|'oklab'|'oklch'`, `scaleMode: 'nearest'` (hard square pixels when scaled up: pixel art; default `'linear'`, smooth; it belongs to the asset). Default anchor top-left; natural size = `w`,`h`.
|
|
179
|
+
**image** — `asset`, `tint`, `colorSpace: 'rgb'|'oklab'|'oklch'`, `scaleMode: 'nearest'` (hard square pixels when scaled up: pixel art; default `'linear'`, smooth; it belongs to the asset). Default anchor top-left; natural size = `w`,`h`. `scale: 2` keeps the ratio; **`width` or `height` alone sets that side only and stretches the picture** (PixiJS: it changes `scale.x` or `scale.y`); `initial: { scale: 'cover' | 'contain' }` fits the image to the canvas (as for video) and keeps its ratio.
|
|
180
180
|
|
|
181
181
|
**video** — `asset`, `loop`, `audio`, `volume`, **`speed`**; `initial: { scale: 'cover' }`. `speed: 0.5` slow motion, `speed: -1` backward (it starts at |speed| × `duration`, so a 3 s file with no `duration` plays whole, backward); with no `duration` the layer lasts the file's length ÷ |speed|. For anything that is not one straight speed — a freeze, a ramp, a loop — animate **`time`** (seconds in the file) like any property: `keyframes: [{ at: 0, from: { time: 0 }, to: { time: 2 }, duration: 1 }, { at: 1, to: { time: 2 }, duration: 0.5 }, { at: 1.5, to: { time: 6 }, duration: 3, ease: 'power2.inOut' }]` (play 2 s, hold, then accelerate). `repeat` loops it, `yoyo` ping-pongs. `speed` itself is not animatable (it warns): animate `time`. The sound follows (pitch too, like a tape).
|
|
182
182
|
|
|
@@ -2373,7 +2373,7 @@ interface SequenceCommon {
|
|
|
2373
2373
|
| `text`, `image`, `video` | the **top-left** corner | `anchorX` / `anchorY: 0.5` to centre |
|
|
2374
2374
|
| `composition` | its top-left corner | `pivotX` / `pivotY` = the point that sits at `x, y` and that rotation / scale turn about |
|
|
2375
2375
|
|
|
2376
|
-
Shape geometry (`width height radius anchorX …`) may be written at the top level or in `initial`; the top level wins. `rotation`, `skew*` and `rotationX/Y` are in **degrees
|
|
2376
|
+
Shape geometry (`width height radius anchorX …`) may be written at the top level or in `initial`; the top level wins. `rotation`, `skew*` and `rotationX/Y` are in **degrees**; a positive `rotation` turns **clockwise** on the screen (+x toward +y, like CSS `rotate()`), about the anchor (a composition: about `pivotX` / `pivotY`, scale first and then rotation). **`skewX` / `skewY` are PixiJS's, not CSS's shear:** they turn an axis about the layer's anchor (the anchored point stays), so `skewX: 40` tilts the layer's vertical edges by 40° and shortens them to `cos 40°` of their length (a CSS `skewX(40deg)` or After Effects' skew keeps the height and moves the bottom by `h · tan 40°`). A point (x, y) of the layer, measured from its anchor, lands at `(x cos β + y sin α, x sin β + y cos α)` for `skewX: α`, `skewY: β`. Pinned by `tests/films/geometry-skew`.
|
|
2377
2377
|
|
|
2378
2378
|
A layer is **not removed** when its lifespan `[at, at + duration)` ends: it is only hidden, and it keeps its last animated values. Outside the lifespan it is invisible. **z-order is array order** (later = on top). Build scenes by giving layers `at` / `duration` and stacking them; a full-screen background rect in each scene hides what is below it.
|
|
2379
2379
|
|
|
@@ -2680,7 +2680,7 @@ Every primitive draws centred on its local origin (so `anchorX`/`anchorY` and `p
|
|
|
2680
2680
|
keyframes: [{ at: 0, to: { trimEnd: 1 }, duration: 1, ease: 'power2.inOut' }] } // a check mark drawing itself
|
|
2681
2681
|
```
|
|
2682
2682
|
|
|
2683
|
-
**Morph (`morphTo` / `morph`).** (Two outlines with the **same number of corners
|
|
2683
|
+
**Morph (`morphTo` / `morph`).** (Two outlines with the **same number of corners** (the points of the outline as written: a line back to the start before `Z` is not a corner, but an extra point on an edge IS one), such as two quads, are paired corner to corner, the start of each outline lined up with the nearest of the other's, so every in-between picture is a straight-edged quad and no corner is rounded; `morphPoints` only matters when the corner counts differ or the outlines are curves.) A `path` can turn into another outline: give `morphTo` (SVG path data in the same canvas coordinates as `d`) and animate `morph` from 0 (the `d` outline) to 1 (the `morphTo` outline). In between it is drawn as a polygon of points half way from one to the other (`morphPoints`: 8–2048, default 128). Closed outlines are lined up (start point and direction) so they do not twist; sub-paths are paired in order, and an extra one grows from (or shrinks into) its own centre. Fill and stroke both follow, and `trimStart` / `trimEnd` walk the morphing outline. Write both outlines as `M … L … C … Z` in absolute coordinates (arcs and holes work too, but keep the same number of sub-paths on both sides).
|
|
2684
2684
|
|
|
2685
2685
|
```ts
|
|
2686
2686
|
{ type: 'shape', shape: 'path', d: 'M 640 160 C 780 160 860 260 860 360 C 860 470 770 560 640 560 C 510 560 420 470 420 360 C 420 250 500 160 640 160 Z',
|
|
@@ -2871,7 +2871,7 @@ Place any 2D layer in depth and view it through a camera — After Effects style
|
|
|
2871
2871
|
|
|
2872
2872
|
| Thing | Convention |
|
|
2873
2873
|
|---|---|
|
|
2874
|
-
| Axes | `+x` right, `+y` down, **`+z` toward the viewer** (like CSS `translateZ`). Bigger `z` = nearer = larger on screen. |
|
|
2874
|
+
| Axes | `+x` right, `+y` down, **`+z` toward the viewer** (like CSS `translateZ`). Bigger `z` = nearer = larger on screen: a flat layer at `z` is drawn `camZ / (camZ − z)` times its size, `camZ` being the camera's distance from the picture plane (about 989 for 720p at fov 40: `z = −989` is half size, `z = +495` is twice). A layer at or behind the camera plane (`z ≥ camZ`) is hidden for that frame and says so once: `layer "card" is at or behind the camera plane (z = 1000) and is hidden`. |
|
|
2875
2875
|
| Units | Positions in composition pixels. **Rotations in degrees.** |
|
|
2876
2876
|
| Rotation signs | Same as CSS: `rotationY: 30` swings the right edge away; `rotationX: 30` brings the bottom edge toward you; `rotation` is the Z axis. |
|
|
2877
2877
|
| Rotation centre | The same point 2D `rotation` uses: `anchorX/anchorY` (sprites, text, shapes) or `pivotX/pivotY` (compositions). Set `anchorX: 0.5, anchorY: 0.5` to spin about the centre. |
|
|
@@ -3108,6 +3108,7 @@ The layer's own three.js renderer is `WebGLRenderer` unless you ask for `rendere
|
|
|
3108
3108
|
- Materials that rewrite three's shaders (`onBeforeCompile`, `ShaderMaterial`, `RawShaderMaterial`) do not run on the WebGPU renderer: a layer that chose `renderer: 'webgpu'` stops building, naming the material and the fix (`renderer: 'webgl'`), instead of drawing a picture that is wrong without saying so. Only what `ctx.scene` holds is looked at: a `ShaderMaterial` kept in a scene of your own and drawn through `ctx.renderer` (a post-processing quad) is not found; three then logs `Material "ShaderMaterial" is not compatible` on every render. The built-in `Mesh*Material`s, `InstancedMesh` and `Points` do run.
|
|
3109
3109
|
- **Lights follow the time.** Three's WebGPU renderer updates its light uniforms (and its `time`) once per animation-loop frame, so renders that follow each other in one task (a seek, an export) would all show the same lights and a lamp keyframed with `three.lamp.intensity` would not move. The layer therefore advances three's node frame before each render and gives its `time` the layer's own time (this reaches into a private field of three's renderer: a three that no longer has it makes the layer warn once).
|
|
3110
3110
|
- Measured on one Apple (Metal) machine, headless Chrome, 2026-10-15: the same lit box drew with a mean difference of 0.04–0.06 (of 255) per channel from the WebGL picture (only edge pixels differ). On the repository's own pages the WebGPU picture equals the WebGL one except where a material used `onBeforeCompile` (`three-product-spin`: the floor reflection no longer fades) and where the scene has fog or a hot, thin edge: see "Where the two renderers differ on purpose". The render alone, waiting for the GPU, took about 0.8–0.9 ms either way for a box; for 2,880 instanced rods under two point lights it took about 0.9–1.2 ms on WebGPU against 1.7–2.1 ms on WebGL (1280×720 to 1920×1080). A 90-frame MP4 export took the same time with either (about 22 frames per second: the encode, not three, was the limit).
|
|
3111
|
+
- **2D layers on the two backends** (measured by `tests/films/backends-agree` on the same machine, 2026-10-20: shapes, text, a linear gradient, multiply, alpha, rotation, a blur filter): the mean difference per channel is 0.016–0.021 of 255. Away from edges the pictures are equal (text, gradient, blur and multiply: 0); the only differences are the antialiasing of curved and rotated edges, up to 34/255 on one pixel at alpha 0.6. Another GPU may differ by a little more.
|
|
3111
3112
|
|
|
3112
3113
|
#### Where the two renderers differ on purpose
|
|
3113
3114
|
|
|
@@ -3405,7 +3406,7 @@ interface Keyframe {
|
|
|
3405
3406
|
The four kinds are mutually exclusive per keyframe:
|
|
3406
3407
|
|
|
3407
3408
|
- **`set`** — instantaneous property assignment at `at`.
|
|
3408
|
-
- **`to`** — tween from whatever the property is at `at` to the given values, over `duration`.
|
|
3409
|
+
- **`to`** — tween from whatever the property is at `at` to the given values, over `duration`. **Keyframes on one property run in the order of their `at`, not of the list** (written backwards they play the same). A `to` starts from where the keyframe before it ENDED, so two keyframes of one property that overlap in time make the picture jump: the later one takes over at its `at`, starting from the earlier one's end value (A: x 40 → 160 over 0.5–1.5 s, B: → 280 from 1 s: the layer is at 96 just before 1 s and at 160 just after). Start the second after the first ends. Pinned by `tests/films/time-keyframe-order`.
|
|
3409
3410
|
- **`from`** — tween from the given values back to the current property, over `duration`.
|
|
3410
3411
|
- **`from` + `to`** — full fromTo tween, with explicit start and end values.
|
|
3411
3412
|
|
|
@@ -4410,9 +4411,9 @@ interface SoundReport {
|
|
|
4410
4411
|
duration: number; sampleRate: number; channels: number;
|
|
4411
4412
|
peakDb: number; // the loudest sample, dBFS
|
|
4412
4413
|
loudness: { integratedLufs: number | null; // ITU-R BS.1770; null for a sound under 0.4 s or with nothing above −70 LUFS
|
|
4413
|
-
truePeakDb: number; clippedSamples: number; silences: Array<{ from: number; to: number }> };
|
|
4414
|
+
truePeakDb: number; clippedSamples: number; silences: Array<{ from: number; to: number }> }; // runs of 1 s or more where every channel stays below −60 dBFS, in seconds
|
|
4414
4415
|
windows: Array<{ t: number; rmsDb: number }>; // the level over time
|
|
4415
|
-
notes: string[]; // quiet or loud for web video, little headroom, silent stretches
|
|
4416
|
+
notes: string[]; // quiet or loud for web video, little headroom, silent stretches (`the mix is silent from X s to Y s (N s)`, at most 3, then `and N more silent stretch(es)`)
|
|
4416
4417
|
}
|
|
4417
4418
|
```
|
|
4418
4419
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ name: pixi-effects
|
|
|
3
3
|
description: Use when asked to make, animate, preview or export a video, motion graphics, an animated title, a lower third, kinetic type, a promo, a slideshow with transitions, an animated chart or data story, a social clip, a 2.5D / depth scene, or music and sound for a video, written as code in JavaScript or HTML. pixi-effects is a JS library where a video is a plain-object composition (text, shape, image, video, audio and file-free sfx / music, camera, light and shader layers with keyframes) that plays in the browser, is checked by a tool the agent can run, and exports MP4 / WebM / MOV with no server. Not for a project that already uses another video tool (Remotion, Motion Canvas, ffmpeg); follow that tool instead.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
> Written for pixi-effects 0.47.
|
|
6
|
+
> Written for pixi-effects 0.47.4. Update this skill with `npx skills update`; the newest docs are at https://yjmtmtk.github.io/pixi-effects/
|
|
7
7
|
|
|
8
8
|
# pixi-effects — write a video as data
|
|
9
9
|
|
|
@@ -45,7 +45,7 @@ threeD: true // opt into 2.5D (see below)
|
|
|
45
45
|
blendMode: 'normal' | 'add' | 'screen' | 'multiply' | 'overlay' | 'soft-light' | 'hard-light' | 'color-dodge' | 'color-burn' | 'darken' | 'lighten' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'linear-burn' // CSS names (hyphenated); blends with EVERYTHING BELOW the layer; add / screen brighten (glows), multiply darkens, soft-light / overlay for colour casts and contrast, color-dodge for light sources; on a composition the children each blend (to blend it as one picture: threeD: true or a filter); the 14 new ones cost ~2 ms a layer on WebGL (10+ on screen warns)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Animatable props (`initial` / keyframes): `x y alpha rotation scale scaleX scaleY pivotX pivotY anchorX anchorY skewX skewY tint width height visible autoAlpha
|
|
48
|
+
Animatable props (`initial` / keyframes): `x y alpha rotation scale scaleX scaleY pivotX pivotY anchorX anchorY skewX skewY tint width height visible autoAlpha` (and PixiJS's own shorthands `position positionX positionY anchor pivot skew tilePosition* tileScale*`), plus for shapes their style/geometry, for text `fill`, for audio `volume`, for 3D `z rotationX rotationY`, filter params as `'filters.<name>.<param>'`, three objects as `'three.<obj>.<path>'`. A mistyped property in `initial` or a keyframe says `layer "x": "alhpa" is not an animatable property — did you mean "alpha"? (in initial, set, to or from)` (once per layer however often it is written); a mistyped text style key says `layer "t": style.fontsize is not a text style key — did you mean "fontSize"? (it is ignored). Keys: …` and lists the valid keys (`style.colour` / `style.color` mean `fill`). **These go in `initial` / keyframes, never at the top level of a shape or text layer** (top-level `x`, `rotation`, `strokeColor`, `fillAlpha` each warn `layer "dot": "x" is a property, not a rect shape key, so it is ignored: write it in initial (initial: { x: 40 }) or in a keyframe`; every warning of this kind names the layer, or says "unnamed <type> layer"): the top level of a shape holds its geometry (`width height radius d startAngle endAngle cornerRadius anchorX anchorY`), `trimStart` / `trimEnd`, `strokeCap` / `strokeJoin`, `fillGradient`.
|
|
49
49
|
|
|
50
50
|
Keyframe kinds: `set` (jump at `at`; undone when you seek back), `to` (animate to), `from` (animate from), `from`+`to`; a value may be relative to where the layer stands (`from: { x: '-=36' }` slides in from 36 px to the left of its place). `from` / `from+to` show their start value from the layer's start, so a delayed fade-in needs no `initial.alpha`. `repeat` (finite extra plays), `yoyo`, `repeatDelay` loop any of them (endless repeats are not allowed: `repeat: -1` (the GSAP habit) is refused with a warning, write a count that covers the layer, `repeat: 40`; a `from` keyframe with a later `at` puts its start value on the layer from frame 0, the layer does not wait for the `at`). `ease` = an ease name (`'none'`, `'power2.out'`, `'expo.out'`, `'back.out(1.7)'`, `'elastic.out(1,0.5)'`, `'sine.inOut'`, `'bounce.out'`, **`'cubic-bezier(.4, 0, .2, 1)'`** (CSS syntax, x1 and x2 in 0…1; `.4, 0, .2, 1` is a gentle in-out; `.2, .8, .2, 1` is FRONT-LOADED, not slow motion: half of the change in the first 13 % of the time, 90 % by 39 %, 99 % by 74 %, then a long settle, so what sits at the END of the content gets the glide; `.2, .8, .5, 1` has a shorter tail). `power1…4` are the powers 2…5: `power2` is a cubic, `power2.in` has done only 12.5 % at half time (42 % at three quarters)… and springs: `'spring(mass, stiffness, damping)'` or `'spring.gentle' | 'snappy' | 'bouncy' | 'wobbly' | 'slow'`; **`duration: 'auto'` = the time the spring takes to settle** (presets, settle time / highest value reached as a multiple of the target: `snappy` 0.42 s / 1.01, `gentle` 0.72 s / 1.02, `bouncy` 1.08 s / 1.28, `slow` 1.29 s / 1.00, `wobbly` 1.61 s / 1.40: time the next beat from these) (real physics; with a number `duration` is the settle time and only the damping ratio shapes it; a damping ratio of 1 or more never overshoots, so `spring(1,170,26)` does not bounce: use damping below 20 at stiffness 170; `'auto'` works on keyframes only, not in `animateText` / `orbit` tweens; a `stagger` ease may be a spring, its delays are held inside the spread). Default ease is linear.
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ Keyframe kinds: `set` (jump at `at`; undone when you seek back), `to` (animate t
|
|
|
53
53
|
|
|
54
54
|
**text** — `text`, `resolution` (1–8: draw at N× the pixels so text inside a parent scaled up N× stays sharp), `style` (any PixiJS TextStyle field: `fontSize fontFamily fontWeight fill letterSpacing lineHeight align wordWrap wordWrapWidth stroke dropShadow padding`; expressions OK for numbers), `colorSpace`. Default anchor is **top-left**; use `anchorX/anchorY: 0.5` to centre on `x,y`. A text layer has one animatable number, `value`, printed where the text contains `{value}` (`text: '{value} users'`, `initial: { value: 0 }`, keyframe `to: { value: 2480 }`; `format: { decimals, grouping, pad /* zero-pad the whole part: pad 2 → 05 */, time: 'hh:mm:ss'|'h:mm:ss'|'hh:mm'|'mm:ss'|'m:ss' /* the value in SECONDS as a clock */ }`) — that is how counters work. **Changing text:** a keyframe `set: { text: 'Two' }` swaps the string at that time (undone on seek back; `to` / `from` cannot tween a string); `visibleChars` (number, first N characters; starts at 0 once animated) is a typewriter: `to: { visibleChars: 30 }, duration: 2.4, ease: 'none'` — use `anchorX: 0` + `style.align: 'left'` so it grows rightward. Multi-line text is centre-aligned by default (`style.align: 'left'` to change). **Colour inside one line:** `spans: [{ text: 'type', fill: '#7fa07f' }, ': ', { text: "'a'", fill: '#ffd166', fontWeight: '700' }, ',\n next line']` instead of `text` (strings use the layer's `style`; a span changes only fill / fontWeight / fontStyle / fontVariant / letterSpacing / dropShadow, never a size, font or stroke (those are the layer's `style`); `\n` starts a line; `style.align: 'left'` for code; `visibleChars` types over all the spans; it becomes a group of text layers `<name>.0…`).
|
|
55
55
|
|
|
56
|
-
**image** — `asset`, `tint`, `colorSpace: 'rgb'|'oklab'|'oklch'`, `scaleMode: 'nearest'` (hard square pixels when scaled up: pixel art; default `'linear'`, smooth; it belongs to the asset). Default anchor top-left; natural size = `w`,`h`.
|
|
56
|
+
**image** — `asset`, `tint`, `colorSpace: 'rgb'|'oklab'|'oklch'`, `scaleMode: 'nearest'` (hard square pixels when scaled up: pixel art; default `'linear'`, smooth; it belongs to the asset). Default anchor top-left; natural size = `w`,`h`. `scale: 2` keeps the ratio; **`width` or `height` alone sets that side only and stretches the picture** (PixiJS: it changes `scale.x` or `scale.y`); `initial: { scale: 'cover' | 'contain' }` fits the image to the canvas (as for video) and keeps its ratio.
|
|
57
57
|
|
|
58
58
|
**video** — `asset`, `loop`, `audio`, `volume`, **`speed`**; `initial: { scale: 'cover' }`. `speed: 0.5` slow motion, `speed: -1` backward (it starts at |speed| × `duration`, so a 3 s file with no `duration` plays whole, backward); with no `duration` the layer lasts the file's length ÷ |speed|. For anything that is not one straight speed — a freeze, a ramp, a loop — animate **`time`** (seconds in the file) like any property: `keyframes: [{ at: 0, from: { time: 0 }, to: { time: 2 }, duration: 1 }, { at: 1, to: { time: 2 }, duration: 0.5 }, { at: 1.5, to: { time: 6 }, duration: 3, ease: 'power2.inOut' }]` (play 2 s, hold, then accelerate). `repeat` loops it, `yoyo` ping-pongs. `speed` itself is not animatable (it warns): animate `time`. The sound follows (pitch too, like a tape).
|
|
59
59
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>pixi-effects video</title>
|
|
7
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
7
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/loader.css" /> <!-- the loader: HTML + CSS only, so it is on screen at once and keeps moving while the page builds the video -->
|
|
8
8
|
<style>
|
|
9
9
|
body { background: #0d1220; margin: 0; padding: 16px; }
|
|
10
10
|
.stage { position: relative; width: min(960px, 100%); } /* the player and the loader both sit inside this box */
|
|
@@ -37,17 +37,17 @@
|
|
|
37
37
|
"imports": {
|
|
38
38
|
"pixi.js": "https://esm.sh/pixi.js@8.22.0?bundle-deps",
|
|
39
39
|
"mediabunny": "https://esm.sh/mediabunny",
|
|
40
|
-
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
41
|
-
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
42
|
-
"pixi-effects/present": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
43
|
-
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
40
|
+
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/index.js",
|
|
41
|
+
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/Controller.js",
|
|
42
|
+
"pixi-effects/present": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/present.js",
|
|
43
|
+
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/three.js",
|
|
44
44
|
"pixi-filters": "https://esm.sh/pixi-filters@6.1.5?external=pixi.js",
|
|
45
45
|
"three": "https://esm.sh/three@0.178.0",
|
|
46
46
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.178.0/examples/jsm/"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
</script>
|
|
50
|
-
<link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.47.
|
|
50
|
+
<link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.47.4/dist/index.js" /> <!-- after the import map: the library downloads while the page is parsed -->
|
|
51
51
|
|
|
52
52
|
<script type="module">
|
|
53
53
|
import { Movie, kenBurns, withFade } from 'pixi-effects';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { CompositionSequence } from './chunk-HX73PCVU.js';
|
|
2
|
-
import './chunk-HGKXEPDJ.js';
|
|
3
|
-
import './chunk-PC7DFDCV.js';
|
|
4
|
-
import './chunk-JVO2W77G.js';
|
|
5
|
-
import './chunk-BXOCEZ4U.js';
|
|
6
|
-
//# sourceMappingURL=Composition-6TXRN65C.js.map
|
|
7
|
-
//# sourceMappingURL=Composition-6TXRN65C.js.map
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkGDY56V74_cjs = require('./chunk-GDY56V74.cjs');
|
|
4
|
-
require('./chunk-33OVRSXF.cjs');
|
|
5
|
-
require('./chunk-RU4N3B5B.cjs');
|
|
6
|
-
require('./chunk-YSTOH5PC.cjs');
|
|
7
|
-
require('./chunk-TWZNOUM7.cjs');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Object.defineProperty(exports, "CompositionSequence", {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function () { return chunkGDY56V74_cjs.CompositionSequence; }
|
|
14
|
-
});
|
|
15
|
-
//# sourceMappingURL=Composition-IC274CKO.cjs.map
|
|
16
|
-
//# sourceMappingURL=Composition-IC274CKO.cjs.map
|