pixi-effects 0.9.0 → 0.10.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 +15 -0
- package/README.md +6 -6
- package/ai/SKILL.md +2 -1
- package/ai/reference/cheatsheet.md +13 -5
- package/ai/reference/pitfalls.md +2 -2
- package/ai/reference/recipes.md +123 -2
- package/ai/template.html +3 -3
- package/dist/{Base-CSIulyIq.d.cts → Base-CwUxTfja.d.cts} +1 -1
- package/dist/{Base-DVgwyIUj.d.ts → Base-CyvSLoCP.d.ts} +1 -1
- package/dist/Composition-EKVTUYCI.cjs +14 -0
- package/dist/{Composition-CM62XJKT.cjs.map → Composition-EKVTUYCI.cjs.map} +1 -1
- package/dist/Composition-NJCOMGD7.js +5 -0
- package/dist/{Composition-RJDSQYTV.js.map → Composition-NJCOMGD7.js.map} +1 -1
- package/dist/Controller.cjs +34 -0
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +12 -2
- package/dist/Controller.d.ts +12 -2
- package/dist/Controller.js +34 -0
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-QMlFyHkf.d.ts → Movie-puD9oZPg.d.ts} +1 -1
- package/dist/{Movie-qGHp15c_.d.cts → Movie-w3GliuP3.d.cts} +1 -1
- package/dist/{chunk-PDBDDGG5.cjs → chunk-4WJUSDJJ.cjs} +103 -30
- package/dist/chunk-4WJUSDJJ.cjs.map +1 -0
- package/dist/{chunk-FNKSXBKB.js → chunk-JAMNDBXW.js} +193 -14
- package/dist/chunk-JAMNDBXW.js.map +1 -0
- package/dist/{chunk-AGMNSJJH.cjs → chunk-S3ZI4MKS.cjs} +196 -12
- package/dist/chunk-S3ZI4MKS.cjs.map +1 -0
- package/dist/{chunk-O4AJYUPK.js → chunk-WDGAVOMS.js} +85 -12
- package/dist/chunk-WDGAVOMS.js.map +1 -0
- package/dist/index.cjs +309 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +231 -5
- package/dist/index.d.ts +231 -5
- package/dist/index.js +282 -11
- package/dist/index.js.map +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-oJijbn-K.d.ts → types-BXu28nJj.d.cts} +26 -2
- package/dist/{types-oJijbn-K.d.cts → types-BXu28nJj.d.ts} +26 -2
- package/docs/api.md +1 -0
- package/docs/dsl.md +108 -2
- package/llms-full.txt +249 -12
- package/package.json +1 -1
- package/dist/Composition-CM62XJKT.cjs +0 -14
- package/dist/Composition-RJDSQYTV.js +0 -5
- package/dist/chunk-AGMNSJJH.cjs.map +0 -1
- package/dist/chunk-FNKSXBKB.js.map +0 -1
- package/dist/chunk-O4AJYUPK.js.map +0 -1
- package/dist/chunk-PDBDDGG5.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CompositionSequence } from './chunk-
|
|
2
|
-
import { ensureFilterLibrary, homeDistance, DEFAULT_FOV, DEG, resolveAt, collectPropKeys } from './chunk-
|
|
3
|
-
export { registerSequenceType } from './chunk-
|
|
1
|
+
import { CompositionSequence } from './chunk-WDGAVOMS.js';
|
|
2
|
+
import { ensureFilterLibrary, homeDistance, DEFAULT_FOV, flattenSvgPath, random, rand, DEG, resolveAt, collectPropKeys } from './chunk-JAMNDBXW.js';
|
|
3
|
+
export { noise, rand, random, registerSequenceType } from './chunk-JAMNDBXW.js';
|
|
4
4
|
import { warnUnknownOptions, suggestName } from './chunk-DKGG7WD4.js';
|
|
5
5
|
import * as PIXI from 'pixi.js';
|
|
6
6
|
import { extensions, CullerPlugin, Application, Container, Rectangle, Culler, CanvasTextMetrics, TextStyle, Assets, ExtensionType, Filter, UniformGroup, GpuProgram, GlProgram, defaultFilterVert } from 'pixi.js';
|
|
@@ -1153,12 +1153,12 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1153
1153
|
blending.add(w.to);
|
|
1154
1154
|
}
|
|
1155
1155
|
}
|
|
1156
|
-
comp.layers().forEach(({ seq, display, threeD }, i) => {
|
|
1156
|
+
comp.layers().forEach(({ seq, display, threeD, carriers }, i) => {
|
|
1157
1157
|
const t = seq.target;
|
|
1158
1158
|
const name = seq.spec.name;
|
|
1159
1159
|
const label = name ?? `${seq.spec.type}#${i}`;
|
|
1160
|
-
const alpha = t?.alpha ?? 1;
|
|
1161
|
-
const alive = threeD ? display.visible : t?.renderable ?? true;
|
|
1160
|
+
const alpha = (t?.alpha ?? 1) * carriers.reduce((a, c) => a * (c.target?.alpha ?? 1), 1);
|
|
1161
|
+
const alive = (threeD ? display.visible : t?.renderable ?? true) && carriers.every((c) => c.target?.renderable ?? true);
|
|
1162
1162
|
const visible = parentVisible && alive && alpha > 0;
|
|
1163
1163
|
let bounds = null;
|
|
1164
1164
|
if (!insideThreeD) {
|
|
@@ -1173,9 +1173,16 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1173
1173
|
if (area === 0) onCanvas = "none";
|
|
1174
1174
|
}
|
|
1175
1175
|
const keys = collectPropKeys(seq.spec);
|
|
1176
|
-
const
|
|
1177
|
-
|
|
1178
|
-
|
|
1176
|
+
const carried = carriers.some((c) => {
|
|
1177
|
+
const k = collectPropKeys(c.spec);
|
|
1178
|
+
return (c.spec.keyframes ?? []).length > 0 && (k.has("x") || k.has("y") || k.has("rotation") || k.has("scale"));
|
|
1179
|
+
});
|
|
1180
|
+
const moving = parentMoving || carried || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
|
|
1181
|
+
const zeroScale = (o) => {
|
|
1182
|
+
const s = o?.scale;
|
|
1183
|
+
return !!s && (s.x === 0 || s.y === 0);
|
|
1184
|
+
};
|
|
1185
|
+
const zero = parentZero || zeroScale(t) || carriers.some((c) => zeroScale(c.target));
|
|
1179
1186
|
const info = { path: prefix + label, name, type: seq.spec.type, threeD, visible, alpha, moving, bounds, onCanvas };
|
|
1180
1187
|
layers.push(info);
|
|
1181
1188
|
let shown = bounds ? clip(bounds, view) : null;
|
|
@@ -1308,7 +1315,8 @@ var COLORS = {
|
|
|
1308
1315
|
audio: "#ff7aa8",
|
|
1309
1316
|
composition: "#8ea4c8",
|
|
1310
1317
|
three: "#ff9f68",
|
|
1311
|
-
camera: "#b0b0b0"
|
|
1318
|
+
camera: "#b0b0b0",
|
|
1319
|
+
null: "#b0b0b0"
|
|
1312
1320
|
};
|
|
1313
1321
|
var esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1314
1322
|
var num = (n) => String(Math.round(n * 100) / 100);
|
|
@@ -2136,6 +2144,269 @@ function orbit(opts) {
|
|
|
2136
2144
|
return spec;
|
|
2137
2145
|
}
|
|
2138
2146
|
|
|
2147
|
+
// src/presets/followPath.ts
|
|
2148
|
+
var KEYS = ["d", "at", "duration", "ease", "from", "to", "orient", "rotate", "frameRate"];
|
|
2149
|
+
var MAX_STEPS = 2e3;
|
|
2150
|
+
function followPath(opts) {
|
|
2151
|
+
warnUnknownOptions("followPath()", opts, KEYS);
|
|
2152
|
+
const { d, at = 0, duration, ease = "none", from = 0, to = 1, orient = false, rotate = 0, frameRate = 30 } = opts;
|
|
2153
|
+
if (typeof d !== "string" || d.trim() === "") throw new Error('followPath(): d must be SVG path data, e.g. "M 100 600 C 300 100 900 100 1180 600"');
|
|
2154
|
+
if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`followPath(): duration must be a positive number of seconds, got ${duration}`);
|
|
2155
|
+
if (!(Number.isFinite(frameRate) && frameRate > 0)) throw new Error(`followPath(): frameRate must be a positive number (samples per second), got ${frameRate}`);
|
|
2156
|
+
for (const [n, v] of [["from", from], ["to", to]]) {
|
|
2157
|
+
if (!(Number.isFinite(v) && v >= 0 && v <= 1)) throw new Error(`followPath(): ${n} must be a fraction of the path between 0 and 1, got ${v}`);
|
|
2158
|
+
}
|
|
2159
|
+
const steps = Math.max(1, Math.round(duration * frameRate));
|
|
2160
|
+
if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
|
|
2161
|
+
const segments = [];
|
|
2162
|
+
let total = 0;
|
|
2163
|
+
for (const line of flattenSvgPath(d)) {
|
|
2164
|
+
const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
|
|
2165
|
+
for (let i = 2; i < p.length; i += 2) {
|
|
2166
|
+
const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
|
|
2167
|
+
if (len === 0) continue;
|
|
2168
|
+
segments.push({ x0: p[i - 2], y0: p[i - 1], x1: p[i], y1: p[i + 1], start: total, len });
|
|
2169
|
+
total += len;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
if (!(total > 0)) throw new Error(`followPath(): the path "${d}" has no length (it needs at least two different points)`);
|
|
2173
|
+
const find = (s) => {
|
|
2174
|
+
let lo = 0, hi = segments.length - 1;
|
|
2175
|
+
while (lo < hi) {
|
|
2176
|
+
const mid = lo + hi >> 1;
|
|
2177
|
+
if (segments[mid].start + segments[mid].len < s) lo = mid + 1;
|
|
2178
|
+
else hi = mid;
|
|
2179
|
+
}
|
|
2180
|
+
return segments[lo];
|
|
2181
|
+
};
|
|
2182
|
+
const at_ = (fraction) => {
|
|
2183
|
+
const s = Math.min(Math.max(fraction, 0), 1) * total;
|
|
2184
|
+
const g = find(s);
|
|
2185
|
+
const t = Math.min(Math.max((s - g.start) / g.len, 0), 1);
|
|
2186
|
+
return { x: g.x0 + (g.x1 - g.x0) * t, y: g.y0 + (g.y1 - g.y0) * t, heading: Math.atan2(g.y1 - g.y0, g.x1 - g.x0) * 180 / Math.PI };
|
|
2187
|
+
};
|
|
2188
|
+
const shape = parseEase(ease);
|
|
2189
|
+
const round2 = (v) => Math.round(v * 1e6) / 1e6;
|
|
2190
|
+
let turn = 0;
|
|
2191
|
+
const sample = (k) => {
|
|
2192
|
+
const p = from + (to - from) * shape(k / steps);
|
|
2193
|
+
const pt = at_(p);
|
|
2194
|
+
const out2 = { x: round2(pt.x), y: round2(pt.y) };
|
|
2195
|
+
if (orient) {
|
|
2196
|
+
let h = pt.heading + rotate;
|
|
2197
|
+
if (k === 0) turn = h;
|
|
2198
|
+
else {
|
|
2199
|
+
let delta = h - turn;
|
|
2200
|
+
delta -= 360 * Math.round(delta / 360);
|
|
2201
|
+
turn += delta;
|
|
2202
|
+
}
|
|
2203
|
+
out2.rotation = round2(turn);
|
|
2204
|
+
}
|
|
2205
|
+
return out2;
|
|
2206
|
+
};
|
|
2207
|
+
const out = [{ at, set: sample(0) }];
|
|
2208
|
+
const step = duration / steps;
|
|
2209
|
+
for (let k = 1; k <= steps; k++) out.push({ at: round2(at + (k - 1) * step), to: sample(k), duration: round2(step), ease: "none" });
|
|
2210
|
+
return out;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
// src/presets/stagger.ts
|
|
2214
|
+
var STAGGER_KEYS = ["each", "amount", "from", "grid", "ease", "seed"];
|
|
2215
|
+
var FROM_NAMES = ["start", "end", "center", "edges", "random"];
|
|
2216
|
+
function stagger(items, options = {}) {
|
|
2217
|
+
const isCount = typeof items === "number";
|
|
2218
|
+
const n = isCount ? items : items.length;
|
|
2219
|
+
if (!Number.isInteger(n) || n < 0) throw new Error(`stagger(): count must be a whole number of items, got ${n}`);
|
|
2220
|
+
warnUnknownOptions("stagger()", options, STAGGER_KEYS);
|
|
2221
|
+
const { each, amount, from = "start", grid, ease = "none", seed = 0 } = options;
|
|
2222
|
+
if (each !== void 0 && amount !== void 0) throw new Error("stagger(): give `each` (seconds between neighbours) or `amount` (seconds in total), not both");
|
|
2223
|
+
if (each !== void 0 && !(Number.isFinite(each) && each >= 0)) throw new Error(`stagger(): each must be a number of seconds >= 0, got ${each}`);
|
|
2224
|
+
if (amount !== void 0 && !(Number.isFinite(amount) && amount >= 0)) throw new Error(`stagger(): amount must be a number of seconds >= 0, got ${amount}`);
|
|
2225
|
+
if (typeof from === "string" && !FROM_NAMES.includes(from)) {
|
|
2226
|
+
throw new Error(`stagger(): from "${from}" is not one of ${FROM_NAMES.map((f) => `"${f}"`).join(", ")} or an item index`);
|
|
2227
|
+
}
|
|
2228
|
+
if (typeof from === "number" && !(Number.isInteger(from) && from >= 0 && from < Math.max(n, 1))) throw new Error(`stagger(): from ${from} is not an index of the ${n} items`);
|
|
2229
|
+
if (grid && !(Array.isArray(grid) && grid.length === 2 && grid.every((g) => Number.isInteger(g) && g > 0) && grid[0] * grid[1] >= n)) {
|
|
2230
|
+
throw new Error(`stagger(): grid must be [columns, rows] and hold all ${n} items, got ${JSON.stringify(grid)}`);
|
|
2231
|
+
}
|
|
2232
|
+
const dist = distances(n, from, grid, seed);
|
|
2233
|
+
const max = dist.reduce((m, d) => Math.max(m, d), 0);
|
|
2234
|
+
const total = amount !== void 0 ? amount : (each ?? 0.1) * max;
|
|
2235
|
+
const shape = parseEase(ease);
|
|
2236
|
+
const delays = dist.map((d) => max === 0 ? 0 : Math.round(total * shape(d / max) * 1e6) / 1e6);
|
|
2237
|
+
if (isCount) return delays;
|
|
2238
|
+
return items.map((layer, i) => ({ ...layer, at: Math.round(((layer.at ?? 0) + delays[i]) * 1e6) / 1e6 }));
|
|
2239
|
+
}
|
|
2240
|
+
function distances(n, from, grid, seed) {
|
|
2241
|
+
if (n === 0) return [];
|
|
2242
|
+
if (from === "random") {
|
|
2243
|
+
const order = Array.from({ length: n }, (_, i) => i);
|
|
2244
|
+
const r = random(seed);
|
|
2245
|
+
for (let i = n - 1; i > 0; i--) {
|
|
2246
|
+
const j = Math.floor(r() * (i + 1));
|
|
2247
|
+
[order[i], order[j]] = [order[j], order[i]];
|
|
2248
|
+
}
|
|
2249
|
+
return order;
|
|
2250
|
+
}
|
|
2251
|
+
if (!grid) {
|
|
2252
|
+
const mid = (n - 1) / 2;
|
|
2253
|
+
return Array.from({ length: n }, (_, i) => {
|
|
2254
|
+
switch (from) {
|
|
2255
|
+
case "start":
|
|
2256
|
+
return i;
|
|
2257
|
+
case "end":
|
|
2258
|
+
return n - 1 - i;
|
|
2259
|
+
case "center":
|
|
2260
|
+
return Math.abs(i - mid);
|
|
2261
|
+
case "edges":
|
|
2262
|
+
return mid - Math.abs(i - mid);
|
|
2263
|
+
default:
|
|
2264
|
+
return Math.abs(i - from);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
const [cols, rows] = grid;
|
|
2269
|
+
const at = (i) => ({ x: i % cols, y: Math.floor(i / cols) });
|
|
2270
|
+
const origin = from === "start" ? { x: 0, y: 0 } : from === "end" ? { x: cols - 1, y: rows - 1 } : from === "center" || from === "edges" ? { x: (cols - 1) / 2, y: (rows - 1) / 2 } : at(from);
|
|
2271
|
+
const d = Array.from({ length: n }, (_, i) => Math.hypot(at(i).x - origin.x, at(i).y - origin.y));
|
|
2272
|
+
if (from !== "edges") return d;
|
|
2273
|
+
const far = Math.max(...d);
|
|
2274
|
+
return d.map((v) => far - v);
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
// src/presets/wiggle.ts
|
|
2278
|
+
var WIGGLE_KEYS = ["at", "duration", "freq", "seed", "ease", "props"];
|
|
2279
|
+
var MAX_STEPS2 = 2e3;
|
|
2280
|
+
function wiggle(opts) {
|
|
2281
|
+
warnUnknownOptions("wiggle()", opts, WIGGLE_KEYS);
|
|
2282
|
+
const { at = 0, duration, freq = 3, seed = 0, ease = "sine.inOut", props } = opts;
|
|
2283
|
+
if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`wiggle(): duration must be a positive number of seconds, got ${duration}`);
|
|
2284
|
+
if (!(Number.isFinite(freq) && freq > 0)) throw new Error(`wiggle(): freq must be a positive number (steps per second), got ${freq}`);
|
|
2285
|
+
const names = Object.keys(props ?? {});
|
|
2286
|
+
if (names.length === 0) throw new Error("wiggle(): props is empty; name at least one property, e.g. props: { x: { around: 100, amp: 8 } }");
|
|
2287
|
+
for (const n of names) {
|
|
2288
|
+
const p = props[n];
|
|
2289
|
+
if (!Number.isFinite(p.amp)) throw new Error(`wiggle(): props.${n}.amp must be a number, got ${p.amp}`);
|
|
2290
|
+
if (p.around === void 0 || p.around === null || p.around === "") throw new Error(`wiggle(): props.${n}.around is missing`);
|
|
2291
|
+
}
|
|
2292
|
+
const steps = Math.ceil(duration * freq - 1e-9);
|
|
2293
|
+
if (steps > MAX_STEPS2) throw new Error(`wiggle(): ${steps} steps is too many (max ${MAX_STEPS2}); lower freq or duration`);
|
|
2294
|
+
const set = {};
|
|
2295
|
+
for (const n of names) set[n] = props[n].around;
|
|
2296
|
+
const out = [{ at, set }];
|
|
2297
|
+
const stepLen = duration / steps;
|
|
2298
|
+
for (let s = 0; s < steps; s++) {
|
|
2299
|
+
const to = {};
|
|
2300
|
+
names.forEach((n, pi) => {
|
|
2301
|
+
const p = props[n];
|
|
2302
|
+
if (s === steps - 1) {
|
|
2303
|
+
to[n] = p.around;
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
const off = (rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
|
|
2307
|
+
to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
|
|
2308
|
+
});
|
|
2309
|
+
out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
|
|
2310
|
+
}
|
|
2311
|
+
return out;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
// src/presets/animateText.ts
|
|
2315
|
+
var KEYS2 = ["by", "x", "y", "align", "name", "at", "duration", "in", "out", "stagger", "idle", "styleFor"];
|
|
2316
|
+
var PRESETS = {
|
|
2317
|
+
rise: { from: { y: 40, alpha: 0 }, duration: 0.5, ease: "back.out(2)" },
|
|
2318
|
+
drop: { from: { y: -50, alpha: 0 }, duration: 0.7, ease: "bounce.out" },
|
|
2319
|
+
fade: { from: { alpha: 0 }, duration: 0.5, ease: "power1.out" },
|
|
2320
|
+
pop: { from: { scale: 0, alpha: 0 }, duration: 0.45, ease: "back.out(2.4)" },
|
|
2321
|
+
zoom: { from: { scale: 2.5, alpha: 0 }, duration: 0.6, ease: "power3.out" },
|
|
2322
|
+
slide: { from: { x: -60, alpha: 0 }, duration: 0.5, ease: "power3.out" },
|
|
2323
|
+
spin: { from: { rotation: -90, scale: 0, alpha: 0 }, duration: 0.6, ease: "back.out(1.7)" }
|
|
2324
|
+
};
|
|
2325
|
+
var PRESET_NAMES = Object.keys(PRESETS);
|
|
2326
|
+
function animateText(text, style, options) {
|
|
2327
|
+
warnUnknownOptions("animateText()", options, KEYS2);
|
|
2328
|
+
const { by = "chars", x = 0, y = 0, align = "left", name = "text", at = 0, duration, idle, styleFor } = options;
|
|
2329
|
+
if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`animateText(): duration must be a positive number of seconds (how long until the last piece is gone), got ${duration}`);
|
|
2330
|
+
const pieces = splitText(text, style, { by, x, y, align });
|
|
2331
|
+
if (pieces.length === 0) return [];
|
|
2332
|
+
const lineHeight = measureText("M", style).height;
|
|
2333
|
+
const inTween = options.in === false ? null : resolveTween(options.in ?? "rise", "in");
|
|
2334
|
+
const outTween = options.out === void 0 || options.out === false ? null : resolveTween(options.out, "out");
|
|
2335
|
+
const delays = stagger(pieces.length, options.stagger ?? { each: 0.04 });
|
|
2336
|
+
const wave = Math.max(...delays);
|
|
2337
|
+
const need = (inTween?.duration ?? 0) + (outTween?.duration ?? 0) + wave;
|
|
2338
|
+
if (duration < need - 1e-9) {
|
|
2339
|
+
throw new Error(`animateText(): duration ${duration} is too short for this wave: the entrance${outTween ? ", the exit" : ""} and the stagger need at least ${+need.toFixed(3)} s`);
|
|
2340
|
+
}
|
|
2341
|
+
const end = at + duration;
|
|
2342
|
+
return pieces.map((p, i) => {
|
|
2343
|
+
const cx = p.x + p.width / 2, cy = p.y + lineHeight / 2;
|
|
2344
|
+
const rest = { x: cx, y: cy, alpha: 1, scale: 1, scaleX: 1, scaleY: 1, rotation: 0 };
|
|
2345
|
+
const start = at + delays[i];
|
|
2346
|
+
const len = end - start;
|
|
2347
|
+
const keyframes = [];
|
|
2348
|
+
const place = (key, v) => key === "x" || key === "y" ? rest[key] + v : v;
|
|
2349
|
+
if (inTween) {
|
|
2350
|
+
keyframes.push({
|
|
2351
|
+
at: 0,
|
|
2352
|
+
duration: inTween.duration,
|
|
2353
|
+
ease: inTween.ease,
|
|
2354
|
+
from: Object.fromEntries(Object.entries(inTween.from).map(([k, v]) => [k, place(k, v)])),
|
|
2355
|
+
to: Object.fromEntries(Object.keys(inTween.from).map((k) => [k, inTween.to[k] ?? rest[k]]))
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
let idleEnd = len;
|
|
2359
|
+
if (outTween) {
|
|
2360
|
+
const begin = outTween.duration + (wave - delays[i]);
|
|
2361
|
+
idleEnd = len - begin;
|
|
2362
|
+
keyframes.push({
|
|
2363
|
+
at: -begin,
|
|
2364
|
+
duration: outTween.duration,
|
|
2365
|
+
ease: outTween.ease,
|
|
2366
|
+
from: Object.fromEntries(Object.keys(outTween.from).map((k) => [k, outTween.to[k] ?? rest[k]])),
|
|
2367
|
+
to: Object.fromEntries(Object.entries(outTween.from).map(([k, v]) => [k, place(k, v)]))
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
if (idle) {
|
|
2371
|
+
const props = {};
|
|
2372
|
+
for (const k of ["x", "y", "rotation", "scale"]) if (idle[k] !== void 0) props[k] = { around: rest[k], amp: idle[k] };
|
|
2373
|
+
const freq = idle.freq ?? 1;
|
|
2374
|
+
const from = inTween?.duration ?? 0;
|
|
2375
|
+
if (Object.keys(props).length > 0 && idleEnd - from >= 1 / freq) {
|
|
2376
|
+
keyframes.push(...wiggle({ at: from, duration: idleEnd - from, freq, seed: (idle.seed ?? 0) * 1e3 + i, props }));
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
return {
|
|
2380
|
+
type: "text",
|
|
2381
|
+
name: `${name}-${i}`,
|
|
2382
|
+
text: p.text,
|
|
2383
|
+
style: styleFor ? { ...style, ...styleFor(p) } : style,
|
|
2384
|
+
at: start,
|
|
2385
|
+
duration: len,
|
|
2386
|
+
initial: { x: cx, y: cy, anchorX: 0.5, anchorY: 0.5 },
|
|
2387
|
+
keyframes
|
|
2388
|
+
};
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
function resolveTween(spec, which) {
|
|
2392
|
+
const t = typeof spec === "string" ? { preset: spec } : spec;
|
|
2393
|
+
if (t.preset !== void 0 && !(t.preset in PRESETS)) {
|
|
2394
|
+
const guess = suggestName(String(t.preset), PRESET_NAMES);
|
|
2395
|
+
throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")})`);
|
|
2396
|
+
}
|
|
2397
|
+
const base = t.preset ? PRESETS[t.preset] : void 0;
|
|
2398
|
+
const from = { ...base?.from ?? {}, ...t.from ?? {} };
|
|
2399
|
+
const to = t.to ?? {};
|
|
2400
|
+
const known = /* @__PURE__ */ new Set(["x", "y", "alpha", "scale", "scaleX", "scaleY", "rotation"]);
|
|
2401
|
+
for (const k of Object.keys(from)) {
|
|
2402
|
+
if (!known.has(k) && to[k] === void 0) throw new Error(`animateText(): ${which}.from has "${k}", which has no resting value; give ${which}.to: { ${k}: \u2026 }`);
|
|
2403
|
+
}
|
|
2404
|
+
if (Object.keys(from).length === 0) throw new Error(`animateText(): ${which} needs a preset or a from`);
|
|
2405
|
+
let ease = t.ease ?? base?.ease ?? "power2.out";
|
|
2406
|
+
if (which === "out" && t.ease === void 0) ease = ease.replace(".out", ".in");
|
|
2407
|
+
return { from, to: { ...to }, duration: t.duration ?? base?.duration ?? 0.5, ease };
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2139
2410
|
// src/transforms/withFade.ts
|
|
2140
2411
|
function withFade(spec, opts) {
|
|
2141
2412
|
warnUnknownOptions("withFade()", opts, ["in", "out"]);
|
|
@@ -2156,6 +2427,6 @@ function withFade(spec, opts) {
|
|
|
2156
2427
|
return spec;
|
|
2157
2428
|
}
|
|
2158
2429
|
|
|
2159
|
-
export { Movie, kenBurns, measureText, orbit, splitText, withFade };
|
|
2430
|
+
export { Movie, animateText, followPath, kenBurns, measureText, orbit, splitText, stagger, wiggle, withFade };
|
|
2160
2431
|
//# sourceMappingURL=index.js.map
|
|
2161
2432
|
//# sourceMappingURL=index.js.map
|