@pixodesk/svg-animator-web 1.0.18 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -14
- package/dist/index.cjs +573 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +344 -21
- package/dist/index.d.ts +344 -21
- package/dist/index.js +568 -181
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.umd.js +568 -181
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -984,6 +984,10 @@ var PxMaskedByEffectSchema = implementsInterface()(px.object({
|
|
|
984
984
|
maskUnits: px.string().optional(),
|
|
985
985
|
maskContentUnits: px.string().optional()
|
|
986
986
|
}));
|
|
987
|
+
var PxClipPathEffectSchema = implementsInterface()(px.object({
|
|
988
|
+
d: px.string().optional(),
|
|
989
|
+
animate: PxPropertyAnimationSchema.optional()
|
|
990
|
+
}));
|
|
987
991
|
var PxTrimPathEffectSchema = implementsInterface()(px.object({
|
|
988
992
|
offset: PxAnimatableNumberSchema.optional(),
|
|
989
993
|
range: PxAnimatableVec2Schema.optional(),
|
|
@@ -1035,8 +1039,9 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
|
1035
1039
|
gradientTransform: px.string().optional()
|
|
1036
1040
|
}));
|
|
1037
1041
|
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
1038
|
-
var
|
|
1039
|
-
|
|
1042
|
+
var PxTextPathEffectSchema = implementsInterface()(px.object({
|
|
1043
|
+
path: px.string(),
|
|
1044
|
+
pathOverflow: px.string().optional(),
|
|
1040
1045
|
lengthAdjust: px.string().optional(),
|
|
1041
1046
|
method: px.string().optional(),
|
|
1042
1047
|
spacing: px.string().optional(),
|
|
@@ -1050,12 +1055,13 @@ var PxEffectsSchema = implementsInterface()(px.object({
|
|
|
1050
1055
|
transformation: PxTransformationEffectSchema.optional(),
|
|
1051
1056
|
repeater: PxRepeaterEffectSchema.optional(),
|
|
1052
1057
|
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1058
|
+
clipPath: PxClipPathEffectSchema.optional(),
|
|
1053
1059
|
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1054
1060
|
clone: PxCloneEffectSchema.optional(),
|
|
1055
1061
|
isCombinedShape: px.boolean().optional(),
|
|
1056
1062
|
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
1057
1063
|
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
1058
|
-
|
|
1064
|
+
textPath: PxTextPathEffectSchema.optional(),
|
|
1059
1065
|
text: PxTextEffectSchema.optional()
|
|
1060
1066
|
}));
|
|
1061
1067
|
function validateNodeEffects(root, opts) {
|
|
@@ -1356,6 +1362,17 @@ function formatOffset(o) {
|
|
|
1356
1362
|
return pct + "%";
|
|
1357
1363
|
}
|
|
1358
1364
|
|
|
1365
|
+
// src/effects/clipPathEffect.ts
|
|
1366
|
+
function applyClipPathEffect(node, fx, ctx) {
|
|
1367
|
+
if (!fx || !fx.d && !fx.animate) return node;
|
|
1368
|
+
const clipId = genId(ctx, "clip");
|
|
1369
|
+
const pathChild = { type: "path", d: fx.d };
|
|
1370
|
+
if (fx.animate) pathChild.animate = { d: fx.animate };
|
|
1371
|
+
ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
|
|
1372
|
+
node.clipPath = "url(#" + clipId + ")";
|
|
1373
|
+
return node;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1359
1376
|
// src/effects/maskedByEffect.ts
|
|
1360
1377
|
function applyMaskedByEffect(node, fx, transformation, ctx) {
|
|
1361
1378
|
if (!fx) return node;
|
|
@@ -1798,6 +1815,9 @@ function synthesiseScale(raw, i) {
|
|
|
1798
1815
|
var RETIME_MATERIALISATION_MODE_INLINE_G = false;
|
|
1799
1816
|
function asRetime(r) {
|
|
1800
1817
|
var _a, _b;
|
|
1818
|
+
if (r.timeCrop) {
|
|
1819
|
+
console.warn("retime: `timeCrop` is not supported yet and will be ignored");
|
|
1820
|
+
}
|
|
1801
1821
|
return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
|
|
1802
1822
|
}
|
|
1803
1823
|
function concatRetime(child, parent) {
|
|
@@ -1928,103 +1948,6 @@ function remapKeyframeTimesOnly(node, start, stretch) {
|
|
|
1928
1948
|
}
|
|
1929
1949
|
}
|
|
1930
1950
|
|
|
1931
|
-
// src/effects/textAlongPathEffect.ts
|
|
1932
|
-
function applyTextAlongPathEffect(node, fx, _ctx) {
|
|
1933
|
-
var _a;
|
|
1934
|
-
if (!fx) return node;
|
|
1935
|
-
const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
|
|
1936
|
-
const textPath = {
|
|
1937
|
-
type: "textPath",
|
|
1938
|
-
href,
|
|
1939
|
-
children: (_a = node.children) != null ? _a : []
|
|
1940
|
-
};
|
|
1941
|
-
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
1942
|
-
if (fx.method !== void 0) textPath.method = fx.method;
|
|
1943
|
-
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
1944
|
-
applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
|
|
1945
|
-
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
1946
|
-
node.children = [textPath];
|
|
1947
|
-
return node;
|
|
1948
|
-
}
|
|
1949
|
-
function applyAnimatableNumber(node, attrName, raw) {
|
|
1950
|
-
if (raw === void 0 || raw === null) return;
|
|
1951
|
-
if (typeof raw === "number") {
|
|
1952
|
-
node[attrName] = String(raw);
|
|
1953
|
-
return;
|
|
1954
|
-
}
|
|
1955
|
-
if (typeof raw === "object" && raw !== null) {
|
|
1956
|
-
const obj = raw;
|
|
1957
|
-
if (Array.isArray(obj.keyframes)) {
|
|
1958
|
-
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
1959
|
-
const animate = __spreadValues({}, prevAnimate || {});
|
|
1960
|
-
const block = { keyframes: obj.keyframes };
|
|
1961
|
-
if (obj.loop !== void 0) block.loop = obj.loop;
|
|
1962
|
-
animate[attrName] = block;
|
|
1963
|
-
node.animate = animate;
|
|
1964
|
-
return;
|
|
1965
|
-
}
|
|
1966
|
-
if (typeof obj.value === "number") {
|
|
1967
|
-
node[attrName] = String(obj.value);
|
|
1968
|
-
return;
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
|
|
1973
|
-
// src/effects/elementFactory.ts
|
|
1974
|
-
var jsonElementFactory = (type, props, children) => {
|
|
1975
|
-
const node = { type };
|
|
1976
|
-
for (const k in props) if (props[k] !== void 0) node[k] = props[k];
|
|
1977
|
-
const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
|
|
1978
|
-
if (arr.length) node.children = arr;
|
|
1979
|
-
return node;
|
|
1980
|
-
};
|
|
1981
|
-
|
|
1982
|
-
// src/effects/glyphPathBake.ts
|
|
1983
|
-
function fmt(v, decimals) {
|
|
1984
|
-
return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
|
|
1985
|
-
}
|
|
1986
|
-
function pack(nums, decimals) {
|
|
1987
|
-
let s = "";
|
|
1988
|
-
for (let i = 0; i < nums.length; i++) {
|
|
1989
|
-
const str2 = fmt(nums[i], decimals);
|
|
1990
|
-
if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
|
|
1991
|
-
s += str2;
|
|
1992
|
-
}
|
|
1993
|
-
return s;
|
|
1994
|
-
}
|
|
1995
|
-
function apply(m, x, y) {
|
|
1996
|
-
return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
1997
|
-
}
|
|
1998
|
-
var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
|
|
1999
|
-
function transformPathData(d, m, decimals = 2) {
|
|
2000
|
-
const tokens = [];
|
|
2001
|
-
let match;
|
|
2002
|
-
TOKEN_RE.lastIndex = 0;
|
|
2003
|
-
while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
|
|
2004
|
-
let out = "";
|
|
2005
|
-
let i = 0;
|
|
2006
|
-
const num2 = () => parseFloat(tokens[i++]);
|
|
2007
|
-
while (i < tokens.length) {
|
|
2008
|
-
const cmd = tokens[i++];
|
|
2009
|
-
if (cmd === "M" || cmd === "L") {
|
|
2010
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2011
|
-
out += cmd + pack([x, y], decimals);
|
|
2012
|
-
} else if (cmd === "C") {
|
|
2013
|
-
const [x1, y1] = apply(m, num2(), num2());
|
|
2014
|
-
const [x2, y2] = apply(m, num2(), num2());
|
|
2015
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2016
|
-
out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
|
|
2017
|
-
} else if (cmd === "Q") {
|
|
2018
|
-
const [x1, y1] = apply(m, num2(), num2());
|
|
2019
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2020
|
-
out += "Q" + pack([x1, y1, x, y], decimals);
|
|
2021
|
-
} else if (cmd === "Z" || cmd === "z") {
|
|
2022
|
-
out += "Z";
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
return out;
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
1951
|
// src/PxAnimatorUtil.ts
|
|
2029
1952
|
function bezierToSvgPath(path) {
|
|
2030
1953
|
var _a, _b, _c, _d;
|
|
@@ -2313,6 +2236,8 @@ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
|
2313
2236
|
// Filter
|
|
2314
2237
|
"filterUnits",
|
|
2315
2238
|
"primitiveUnits",
|
|
2239
|
+
"tableValues",
|
|
2240
|
+
// feFuncR/G/B/A transfer table (type="table")
|
|
2316
2241
|
"stdDeviation",
|
|
2317
2242
|
"baseFrequency",
|
|
2318
2243
|
"numOctaves",
|
|
@@ -2569,7 +2494,11 @@ function createPathSampler(d) {
|
|
|
2569
2494
|
};
|
|
2570
2495
|
return {
|
|
2571
2496
|
totalLength,
|
|
2497
|
+
closed,
|
|
2572
2498
|
sampleAtDistance(dist) {
|
|
2499
|
+
if (closed && totalLength > 0 && (dist < 0 || dist > totalLength)) {
|
|
2500
|
+
return sampleOn((dist % totalLength + totalLength) % totalLength);
|
|
2501
|
+
}
|
|
2573
2502
|
if (!closed && (dist < 0 || dist > totalLength)) {
|
|
2574
2503
|
const edge = dist < 0 ? 0 : totalLength;
|
|
2575
2504
|
const p = sampleOn(edge);
|
|
@@ -2581,6 +2510,173 @@ function createPathSampler(d) {
|
|
|
2581
2510
|
};
|
|
2582
2511
|
}
|
|
2583
2512
|
|
|
2513
|
+
// src/effects/textPathEffect.ts
|
|
2514
|
+
var EXTEND_MARGIN_FRAC = 0.15;
|
|
2515
|
+
function numRange(v) {
|
|
2516
|
+
if (typeof v === "number") return { min: v, max: v };
|
|
2517
|
+
if (v && typeof v === "object") {
|
|
2518
|
+
const o = v;
|
|
2519
|
+
if (typeof o.value === "number") return { min: o.value, max: o.value };
|
|
2520
|
+
if (Array.isArray(o.keyframes) && o.keyframes.length) {
|
|
2521
|
+
const vals = o.keyframes.map((k) => Number(k.value) || 0);
|
|
2522
|
+
return { min: Math.min(...vals), max: Math.max(...vals) };
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
return { min: 0, max: 0 };
|
|
2526
|
+
}
|
|
2527
|
+
function estimateTextAdvance(node) {
|
|
2528
|
+
let chars = 0, maxFont = 16;
|
|
2529
|
+
const walk = (el) => {
|
|
2530
|
+
var _a, _b;
|
|
2531
|
+
const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
|
|
2532
|
+
if (fs) maxFont = Math.max(maxFont, fs);
|
|
2533
|
+
const t = (_b = el.text) != null ? _b : el.textContent;
|
|
2534
|
+
if (typeof t === "string") chars += t.length;
|
|
2535
|
+
if (el.children) for (const c of el.children) walk(c);
|
|
2536
|
+
};
|
|
2537
|
+
walk(node);
|
|
2538
|
+
return chars * maxFont;
|
|
2539
|
+
}
|
|
2540
|
+
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
2541
|
+
function shiftAnimatable(v, by) {
|
|
2542
|
+
if (!by || v === void 0 || v === null) return v;
|
|
2543
|
+
if (typeof v === "number") return v + by;
|
|
2544
|
+
const o = v;
|
|
2545
|
+
if (typeof o.value === "number") return __spreadProps(__spreadValues({}, o), { value: o.value + by });
|
|
2546
|
+
if (Array.isArray(o.keyframes)) return __spreadProps(__spreadValues({}, o), { keyframes: o.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by })) });
|
|
2547
|
+
return v;
|
|
2548
|
+
}
|
|
2549
|
+
function extendedPathForBrowser(pathD, opts) {
|
|
2550
|
+
var _a;
|
|
2551
|
+
if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
|
|
2552
|
+
const sampler = createPathSampler(pathD);
|
|
2553
|
+
if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
|
|
2554
|
+
const L = sampler.totalLength;
|
|
2555
|
+
const margin = EXTEND_MARGIN_FRAC * L;
|
|
2556
|
+
const so = numRange(opts.startOffset);
|
|
2557
|
+
const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
|
|
2558
|
+
const startOverflow = Math.max(0, -so.min);
|
|
2559
|
+
const endOverflow = Math.max(0, so.max + runWidth - L);
|
|
2560
|
+
const startExt = startOverflow > 0 ? startOverflow + margin : 0;
|
|
2561
|
+
const endExt = endOverflow > 0 ? endOverflow + margin : 0;
|
|
2562
|
+
if (endExt <= 0 && startExt <= 0) return { d: pathD, startShift: 0 };
|
|
2563
|
+
const s = sampler.sampleAtDistance(0);
|
|
2564
|
+
const e = sampler.sampleAtDistance(L);
|
|
2565
|
+
let d = pathD;
|
|
2566
|
+
if (startExt > 0) {
|
|
2567
|
+
const sx = s.x - Math.cos(s.angle) * startExt, sy = s.y - Math.sin(s.angle) * startExt;
|
|
2568
|
+
const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
|
|
2569
|
+
d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
|
|
2570
|
+
}
|
|
2571
|
+
if (endExt > 0) {
|
|
2572
|
+
const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
|
|
2573
|
+
d += "L" + r3(ex) + "," + r3(ey);
|
|
2574
|
+
}
|
|
2575
|
+
return { d, startShift: startExt };
|
|
2576
|
+
}
|
|
2577
|
+
function applyTextPathEffect(node, fx, ctx) {
|
|
2578
|
+
var _a;
|
|
2579
|
+
if (!fx || typeof fx.path !== "string" || !fx.path) return node;
|
|
2580
|
+
const pathId = genId(ctx, "tpath");
|
|
2581
|
+
const { d, startShift } = extendedPathForBrowser(fx.path, {
|
|
2582
|
+
pathOverflow: fx.pathOverflow,
|
|
2583
|
+
startOffset: fx.startOffset,
|
|
2584
|
+
textLength: fx.textLength,
|
|
2585
|
+
advance: estimateTextAdvance(node)
|
|
2586
|
+
});
|
|
2587
|
+
ctx.defs.push({ type: "path", id: pathId, d });
|
|
2588
|
+
const textPath = {
|
|
2589
|
+
type: "textPath",
|
|
2590
|
+
href: "#" + pathId,
|
|
2591
|
+
children: (_a = node.children) != null ? _a : []
|
|
2592
|
+
};
|
|
2593
|
+
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
2594
|
+
if (fx.method !== void 0) textPath.method = fx.method;
|
|
2595
|
+
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
2596
|
+
applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
|
|
2597
|
+
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
2598
|
+
node.children = [textPath];
|
|
2599
|
+
return node;
|
|
2600
|
+
}
|
|
2601
|
+
function applyAnimatableNumber(node, attrName, raw) {
|
|
2602
|
+
if (raw === void 0 || raw === null) return;
|
|
2603
|
+
if (typeof raw === "number") {
|
|
2604
|
+
node[attrName] = String(raw);
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
if (typeof raw === "object" && raw !== null) {
|
|
2608
|
+
const obj = raw;
|
|
2609
|
+
if (Array.isArray(obj.keyframes)) {
|
|
2610
|
+
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
2611
|
+
const animate = __spreadValues({}, prevAnimate || {});
|
|
2612
|
+
const block = { keyframes: obj.keyframes };
|
|
2613
|
+
if (obj.loop !== void 0) block.loop = obj.loop;
|
|
2614
|
+
animate[attrName] = block;
|
|
2615
|
+
node.animate = animate;
|
|
2616
|
+
return;
|
|
2617
|
+
}
|
|
2618
|
+
if (typeof obj.value === "number") {
|
|
2619
|
+
node[attrName] = String(obj.value);
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
// src/effects/elementFactory.ts
|
|
2626
|
+
var jsonElementFactory = (type, props, children) => {
|
|
2627
|
+
const node = { type };
|
|
2628
|
+
for (const k in props) if (props[k] !== void 0) node[k] = props[k];
|
|
2629
|
+
const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
|
|
2630
|
+
if (arr.length) node.children = arr;
|
|
2631
|
+
return node;
|
|
2632
|
+
};
|
|
2633
|
+
|
|
2634
|
+
// src/effects/glyphPathBake.ts
|
|
2635
|
+
function fmt(v, decimals) {
|
|
2636
|
+
return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
|
|
2637
|
+
}
|
|
2638
|
+
function pack(nums, decimals) {
|
|
2639
|
+
let s = "";
|
|
2640
|
+
for (let i = 0; i < nums.length; i++) {
|
|
2641
|
+
const str2 = fmt(nums[i], decimals);
|
|
2642
|
+
if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
|
|
2643
|
+
s += str2;
|
|
2644
|
+
}
|
|
2645
|
+
return s;
|
|
2646
|
+
}
|
|
2647
|
+
function apply(m, x, y) {
|
|
2648
|
+
return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
2649
|
+
}
|
|
2650
|
+
var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
|
|
2651
|
+
function transformPathData(d, m, decimals = 2) {
|
|
2652
|
+
const tokens = [];
|
|
2653
|
+
let match;
|
|
2654
|
+
TOKEN_RE.lastIndex = 0;
|
|
2655
|
+
while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
|
|
2656
|
+
let out = "";
|
|
2657
|
+
let i = 0;
|
|
2658
|
+
const num2 = () => parseFloat(tokens[i++]);
|
|
2659
|
+
while (i < tokens.length) {
|
|
2660
|
+
const cmd = tokens[i++];
|
|
2661
|
+
if (cmd === "M" || cmd === "L") {
|
|
2662
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2663
|
+
out += cmd + pack([x, y], decimals);
|
|
2664
|
+
} else if (cmd === "C") {
|
|
2665
|
+
const [x1, y1] = apply(m, num2(), num2());
|
|
2666
|
+
const [x2, y2] = apply(m, num2(), num2());
|
|
2667
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2668
|
+
out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
|
|
2669
|
+
} else if (cmd === "Q") {
|
|
2670
|
+
const [x1, y1] = apply(m, num2(), num2());
|
|
2671
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2672
|
+
out += "Q" + pack([x1, y1, x, y], decimals);
|
|
2673
|
+
} else if (cmd === "Z" || cmd === "z") {
|
|
2674
|
+
out += "Z";
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
return out;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2584
2680
|
// src/effects/textGlyphsEffect.ts
|
|
2585
2681
|
var DEFAULT_FONT_SIZE = 16;
|
|
2586
2682
|
var TEXT_ATTR_KEYS = [
|
|
@@ -2659,6 +2755,19 @@ function soleFontOf(glyphs) {
|
|
|
2659
2755
|
const names = Object.keys(glyphs);
|
|
2660
2756
|
return names.length === 1 ? glyphs[names[0]] : void 0;
|
|
2661
2757
|
}
|
|
2758
|
+
var MISSING_GLYPH_ADVANCE_EM = 0.6;
|
|
2759
|
+
function missingGlyphBoxEm(advanceEm, ascentEm) {
|
|
2760
|
+
if (advanceEm <= 0 || ascentEm <= 0) return "";
|
|
2761
|
+
const inset = 0.08;
|
|
2762
|
+
const x0 = advanceEm * inset, x1 = advanceEm * (1 - inset);
|
|
2763
|
+
const y1 = -ascentEm * (1 - inset);
|
|
2764
|
+
const bw = x1 - x0, bh = -y1;
|
|
2765
|
+
const t = Math.max(1, Math.min(bw, bh) * 0.12);
|
|
2766
|
+
const outer = "M" + x0 + " 0L" + x1 + " 0L" + x1 + " " + y1 + "L" + x0 + " " + y1 + "Z";
|
|
2767
|
+
if (bw <= 2 * t || bh <= 2 * t) return outer;
|
|
2768
|
+
const ix0 = x0 + t, ix1 = x1 - t, iyb = -t, iyt = y1 + t;
|
|
2769
|
+
return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
|
|
2770
|
+
}
|
|
2662
2771
|
function materialiseGlyphTextHorizontal(node, opts) {
|
|
2663
2772
|
var _a, _b, _c, _d;
|
|
2664
2773
|
const { glyphs, create = jsonElementFactory, warnings } = opts;
|
|
@@ -2668,15 +2777,26 @@ function materialiseGlyphTextHorizontal(node, opts) {
|
|
|
2668
2777
|
const lines = [{ start: pen.x, end: pen.x }];
|
|
2669
2778
|
let line = 0;
|
|
2670
2779
|
const renderChars = (content, s) => {
|
|
2780
|
+
var _a2;
|
|
2671
2781
|
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2672
|
-
|
|
2673
|
-
const scale = s.fontSize /
|
|
2782
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
2783
|
+
const scale = s.fontSize / upm;
|
|
2784
|
+
const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
|
|
2674
2785
|
const paint = paintOf(s);
|
|
2675
2786
|
for (let i = 0; i < content.length; i++) {
|
|
2676
2787
|
const ch = content.charAt(i);
|
|
2677
|
-
const g = gf.glyphs[ch];
|
|
2678
|
-
if (g && g.d)
|
|
2679
|
-
|
|
2788
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
2789
|
+
if (g && g.d) {
|
|
2790
|
+
placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
|
|
2791
|
+
pen.x += g.width * scale;
|
|
2792
|
+
} else if (/\S/.test(ch)) {
|
|
2793
|
+
const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
|
|
2794
|
+
placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
|
|
2795
|
+
pen.x += advEm * scale;
|
|
2796
|
+
} else {
|
|
2797
|
+
pen.x += (g ? g.width : 0) * scale;
|
|
2798
|
+
}
|
|
2799
|
+
pen.x += s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2680
2800
|
lines[line].end = pen.x;
|
|
2681
2801
|
}
|
|
2682
2802
|
};
|
|
@@ -2711,24 +2831,152 @@ function materialiseGlyphTextHorizontal(node, opts) {
|
|
|
2711
2831
|
}
|
|
2712
2832
|
return toGroup(node, buildPaths(placements, create, warnings), create);
|
|
2713
2833
|
}
|
|
2834
|
+
function layoutGlyphTextChars(node, opts) {
|
|
2835
|
+
var _a, _b, _c, _d, _e;
|
|
2836
|
+
if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
|
|
2837
|
+
const { glyphs, warnings } = opts;
|
|
2838
|
+
const soleFont = soleFontOf(glyphs);
|
|
2839
|
+
const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
|
|
2840
|
+
const boxes = [];
|
|
2841
|
+
const lines = [{ start: pen.x, end: pen.x }];
|
|
2842
|
+
let line = 0;
|
|
2843
|
+
const renderChars = (content, s) => {
|
|
2844
|
+
var _a2;
|
|
2845
|
+
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2846
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
2847
|
+
const scale = s.fontSize / upm;
|
|
2848
|
+
const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
|
|
2849
|
+
for (let i = 0; i < content.length; i++) {
|
|
2850
|
+
const ch = content.charAt(i);
|
|
2851
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
2852
|
+
const advance = (g ? g.width : 0) * scale + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2853
|
+
boxes.push({ x: pen.x, y: pen.y, width: advance, ascent, fontSize: s.fontSize, line });
|
|
2854
|
+
pen.x += advance;
|
|
2855
|
+
lines[line].end = pen.x;
|
|
2856
|
+
}
|
|
2857
|
+
};
|
|
2858
|
+
const walk = (el, parentStyle) => {
|
|
2859
|
+
var _a2, _b2, _c2, _d2;
|
|
2860
|
+
const s = resolveStyle(el, parentStyle);
|
|
2861
|
+
const x = parseLen(el.x);
|
|
2862
|
+
const y = parseLen(el.y);
|
|
2863
|
+
if (x !== void 0) {
|
|
2864
|
+
pen.x = x;
|
|
2865
|
+
line = lines.length;
|
|
2866
|
+
lines.push({ start: pen.x, end: pen.x });
|
|
2867
|
+
}
|
|
2868
|
+
if (y !== void 0) pen.y = y;
|
|
2869
|
+
pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
|
|
2870
|
+
pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
|
|
2871
|
+
const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
|
|
2872
|
+
if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
|
|
2873
|
+
if (el.children) for (const ch of el.children) walk(ch, s);
|
|
2874
|
+
};
|
|
2875
|
+
const rootStyle = rootStyleOf(node);
|
|
2876
|
+
if (node.children) for (const ch of node.children) walk(ch, rootStyle);
|
|
2877
|
+
const rootContent = (_d = str(node[TEXT_ATTR])) != null ? _d : str(node[TEXT_CONTENT_ATTR]);
|
|
2878
|
+
if (rootContent && !((_e = node.children) == null ? void 0 : _e.length)) renderChars(rootContent, rootStyle);
|
|
2879
|
+
const anchor = str(node.textAnchor);
|
|
2880
|
+
if (anchor === "middle" || anchor === "end") {
|
|
2881
|
+
for (const b of boxes) {
|
|
2882
|
+
const w = lines[b.line].end - lines[b.line].start;
|
|
2883
|
+
b.x += anchor === "middle" ? -w / 2 : -w;
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
return boxes.map((_f) => {
|
|
2887
|
+
var _g = _f, { line: _l } = _g, b = __objRest(_g, ["line"]);
|
|
2888
|
+
return b;
|
|
2889
|
+
});
|
|
2890
|
+
}
|
|
2891
|
+
function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
|
|
2892
|
+
var _a;
|
|
2893
|
+
const { glyphs, warnings, alongPath } = opts;
|
|
2894
|
+
const sampler = createPathSampler(pathD);
|
|
2895
|
+
if (!sampler) {
|
|
2896
|
+
warnings == null ? void 0 : warnings.push("textGlyphs: unparsable along-path geometry (caret)");
|
|
2897
|
+
return [];
|
|
2898
|
+
}
|
|
2899
|
+
const soleFont = soleFontOf(glyphs);
|
|
2900
|
+
const chars = [];
|
|
2901
|
+
let adv = 0;
|
|
2902
|
+
const walk = (el, parentStyle) => {
|
|
2903
|
+
var _a2, _b, _c;
|
|
2904
|
+
const s = resolveStyle(el, parentStyle);
|
|
2905
|
+
const content = (_a2 = str(el[TEXT_ATTR])) != null ? _a2 : str(el[TEXT_CONTENT_ATTR]);
|
|
2906
|
+
if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
|
|
2907
|
+
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2908
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
2909
|
+
const scale = s.fontSize / upm;
|
|
2910
|
+
const ascent = ((_c = gf == null ? void 0 : gf.ascent) != null ? _c : 0.9 * upm) * scale;
|
|
2911
|
+
for (let i = 0; i < content.length; i++) {
|
|
2912
|
+
const ch = content.charAt(i);
|
|
2913
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
2914
|
+
const glyphW = (g ? g.width : 0) * scale;
|
|
2915
|
+
const advance = glyphW + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2916
|
+
chars.push({ advStart: adv, advEnd: adv + advance, glyphW, ascent, fontSize: s.fontSize });
|
|
2917
|
+
adv += advance;
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
if (el.children) for (const ch of el.children) walk(ch, s);
|
|
2921
|
+
};
|
|
2922
|
+
walk(node, rootStyleOf(node));
|
|
2923
|
+
const width = adv;
|
|
2924
|
+
const k = (alongPath == null ? void 0 : alongPath.textLength) && alongPath.textLength > 0 && width > 0 ? alongPath.textLength / width : 1;
|
|
2925
|
+
const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
|
|
2926
|
+
const { along: alongOffset, perp } = alongPathNodeOffsets(node);
|
|
2927
|
+
const base = alongOffset + (so.kind === "animated" /* Animated */ ? Number((_a = so.keyframes[0]) == null ? void 0 : _a.value) || 0 : so.kind === "static" /* Static */ ? Number(so.value) || 0 : 0);
|
|
2928
|
+
const withPerp = (p) => ({
|
|
2929
|
+
x: p.x - perp * Math.sin(p.angle),
|
|
2930
|
+
y: p.y + perp * Math.cos(p.angle),
|
|
2931
|
+
angle: p.angle
|
|
2932
|
+
});
|
|
2933
|
+
return chars.map((c) => {
|
|
2934
|
+
const dStart = base + c.advStart * k;
|
|
2935
|
+
const dEnd = base + c.advEnd * k;
|
|
2936
|
+
const p0 = withPerp(sampler.sampleAtDistance(dStart));
|
|
2937
|
+
const p1 = withPerp(sampler.sampleAtDistance(dEnd));
|
|
2938
|
+
const glyphMid = sampler.sampleAtDistance(base + (c.advStart + c.glyphW / 2) * k);
|
|
2939
|
+
return {
|
|
2940
|
+
x: p0.x,
|
|
2941
|
+
y: p0.y,
|
|
2942
|
+
width: c.advEnd - c.advStart,
|
|
2943
|
+
ascent: c.ascent,
|
|
2944
|
+
fontSize: c.fontSize,
|
|
2945
|
+
endX: p1.x,
|
|
2946
|
+
endY: p1.y,
|
|
2947
|
+
rotation: glyphMid.angle * 180 / Math.PI
|
|
2948
|
+
};
|
|
2949
|
+
});
|
|
2950
|
+
}
|
|
2714
2951
|
function collectAlongPathCells(node, glyphs, soleFont, warnings) {
|
|
2715
2952
|
const cells = [];
|
|
2716
2953
|
let adv = 0;
|
|
2717
2954
|
const walk = (el, parentStyle) => {
|
|
2718
|
-
var _a, _b;
|
|
2955
|
+
var _a, _b, _c;
|
|
2719
2956
|
const s = resolveStyle(el, parentStyle);
|
|
2720
2957
|
const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
|
|
2721
2958
|
if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
|
|
2722
2959
|
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2723
2960
|
if (gf) {
|
|
2724
2961
|
const scale = s.fontSize / gf.unitsPerEm;
|
|
2962
|
+
const ascentEm = (_c = gf.ascent) != null ? _c : 0.9 * gf.unitsPerEm;
|
|
2725
2963
|
const paint = paintOf(s);
|
|
2726
2964
|
for (let i = 0; i < content.length; i++) {
|
|
2727
2965
|
const ch = content.charAt(i);
|
|
2728
2966
|
const g = gf.glyphs[ch];
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2967
|
+
if (g && g.d) {
|
|
2968
|
+
const glyphAdv = g.width * scale;
|
|
2969
|
+
cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
|
|
2970
|
+
adv += glyphAdv;
|
|
2971
|
+
} else if (/\S/.test(ch)) {
|
|
2972
|
+
const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
|
|
2973
|
+
const boxAdv = wEm * scale;
|
|
2974
|
+
cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, midBase: adv + boxAdv / 2 });
|
|
2975
|
+
adv += boxAdv;
|
|
2976
|
+
} else {
|
|
2977
|
+
adv += (g ? g.width : 0) * scale;
|
|
2978
|
+
}
|
|
2979
|
+
adv += s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2732
2980
|
}
|
|
2733
2981
|
}
|
|
2734
2982
|
}
|
|
@@ -2737,12 +2985,19 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
|
|
|
2737
2985
|
walk(node, rootStyleOf(node));
|
|
2738
2986
|
return { cells, width: adv };
|
|
2739
2987
|
}
|
|
2740
|
-
function alongAffine(sampler, dist, scale, widthEm) {
|
|
2988
|
+
function alongAffine(sampler, dist, scale, widthEm, perp = 0) {
|
|
2741
2989
|
const { x, y, angle } = sampler.sampleAtDistance(dist);
|
|
2742
2990
|
const cos = Math.cos(angle), sin = Math.sin(angle), hw = widthEm / 2;
|
|
2743
|
-
return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw, y - scale * sin * hw];
|
|
2991
|
+
return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
|
|
2992
|
+
}
|
|
2993
|
+
function alongPathNodeOffsets(node) {
|
|
2994
|
+
var _a, _b, _c;
|
|
2995
|
+
return {
|
|
2996
|
+
along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
|
|
2997
|
+
perp: (_c = parseLen(node.dy)) != null ? _c : 0
|
|
2998
|
+
};
|
|
2744
2999
|
}
|
|
2745
|
-
function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength) {
|
|
3000
|
+
function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
|
|
2746
3001
|
var _a;
|
|
2747
3002
|
const { glyphs, create = jsonElementFactory, warnings } = opts;
|
|
2748
3003
|
const sampler = pathD ? createPathSampler(pathD) : null;
|
|
@@ -2753,19 +3008,25 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
|
|
|
2753
3008
|
const soleFont = soleFontOf(glyphs);
|
|
2754
3009
|
const { cells, width } = collectAlongPathCells(node, glyphs, soleFont, warnings);
|
|
2755
3010
|
if (!cells.length) return toGroup(node, [], create);
|
|
3011
|
+
const { along: alongOffset, perp } = alongPathNodeOffsets(node);
|
|
2756
3012
|
if (textLength && textLength > 0 && width > 0) {
|
|
2757
3013
|
const k = textLength / width;
|
|
2758
3014
|
for (const c of cells) c.midBase *= k;
|
|
2759
3015
|
}
|
|
3016
|
+
const isClip = pathOverflow === "clip" && !sampler.closed;
|
|
2760
3017
|
const so = readAnimatable(startOffset);
|
|
2761
3018
|
if (so.kind === "animated" /* Animated */ && so.keyframes.length >= 2) {
|
|
2762
|
-
return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create), create);
|
|
2763
|
-
}
|
|
2764
|
-
const base = so.kind === "animated" /* Animated */ ? Number((_a = so.keyframes[0]) == null ? void 0 : _a.value) || 0 : so.kind === "static" /* Static */ ? Number(so.value) || 0 : 0;
|
|
2765
|
-
const
|
|
3019
|
+
return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create, isClip, alongOffset, perp), create);
|
|
3020
|
+
}
|
|
3021
|
+
const base = alongOffset + (so.kind === "animated" /* Animated */ ? Number((_a = so.keyframes[0]) == null ? void 0 : _a.value) || 0 : so.kind === "static" /* Static */ ? Number(so.value) || 0 : 0);
|
|
3022
|
+
const placeCells = isClip ? cells.filter((c) => {
|
|
3023
|
+
const d = base + c.midBase;
|
|
3024
|
+
return d >= 0 && d <= sampler.totalLength;
|
|
3025
|
+
}) : cells;
|
|
3026
|
+
const placements = placeCells.map((c) => ({
|
|
2766
3027
|
glyphD: c.glyphD,
|
|
2767
3028
|
paint: c.paint,
|
|
2768
|
-
m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm)
|
|
3029
|
+
m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm, perp)
|
|
2769
3030
|
}));
|
|
2770
3031
|
return toGroup(node, buildPaths(placements, create, warnings), create);
|
|
2771
3032
|
}
|
|
@@ -2775,37 +3036,51 @@ function roundN(v, n) {
|
|
|
2775
3036
|
const f = __pow(10, n);
|
|
2776
3037
|
return Math.round(v * f) / f;
|
|
2777
3038
|
}
|
|
2778
|
-
function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create) {
|
|
3039
|
+
function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create, isClip, alongOffset = 0, perp = 0) {
|
|
2779
3040
|
const step = Math.max(sampler.totalLength / ALONG_PATH_MAX_STEPS, 0.5);
|
|
2780
3041
|
const timeOf = (kf) => Number(kf.time) || 0;
|
|
2781
|
-
const offOf = (kf) => Number(kf.value) || 0;
|
|
3042
|
+
const offOf = (kf) => alongOffset + (Number(kf.value) || 0);
|
|
3043
|
+
const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
|
|
2782
3044
|
const out = [];
|
|
2783
3045
|
for (const c of cells) {
|
|
2784
3046
|
const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
|
|
2785
3047
|
const d = transformPathData(c.glyphD, centred);
|
|
2786
3048
|
const sampleKf = (dist, time) => {
|
|
2787
3049
|
const { x, y, angle } = sampler.sampleAtDistance(dist);
|
|
3050
|
+
const cos = Math.cos(angle), sin = Math.sin(angle);
|
|
2788
3051
|
return {
|
|
2789
3052
|
time,
|
|
2790
3053
|
value: {
|
|
2791
|
-
["translate" /* Translate */]: [roundN(x, 3), roundN(y, 3)],
|
|
3054
|
+
["translate" /* Translate */]: [roundN(x - perp * sin, 3), roundN(y + perp * cos, 3)],
|
|
2792
3055
|
["rotate" /* Rotate */]: roundN(angle * 180 / Math.PI, 3)
|
|
2793
3056
|
}
|
|
2794
3057
|
};
|
|
2795
3058
|
};
|
|
2796
|
-
const kfs = [
|
|
3059
|
+
const kfs = [];
|
|
3060
|
+
const opKfs = [];
|
|
3061
|
+
const pushKf = (dist, time) => {
|
|
3062
|
+
kfs.push(sampleKf(dist, time));
|
|
3063
|
+
if (isClip) opKfs.push({ time, value: onPath(dist) ? 1 : 0 });
|
|
3064
|
+
};
|
|
3065
|
+
pushKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]));
|
|
2797
3066
|
for (let k = 1; k < sokfs.length; k++) {
|
|
2798
3067
|
const t0 = timeOf(sokfs[k - 1]), t1 = timeOf(sokfs[k]);
|
|
2799
3068
|
const o0 = offOf(sokfs[k - 1]), o1 = offOf(sokfs[k]);
|
|
2800
3069
|
const n = Math.min(ALONG_PATH_MAX_STEPS_PER_SEGMENT, Math.max(1, Math.ceil(Math.abs(o1 - o0) / step)));
|
|
2801
3070
|
for (let s = 1; s <= n; s++) {
|
|
2802
3071
|
const f = s / n;
|
|
2803
|
-
|
|
3072
|
+
pushKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0));
|
|
2804
3073
|
}
|
|
2805
3074
|
}
|
|
2806
3075
|
const transform = { keyframes: kfs };
|
|
2807
3076
|
if (loop !== void 0) transform.loop = loop;
|
|
2808
|
-
|
|
3077
|
+
const animate = { transform };
|
|
3078
|
+
if (isClip && opKfs.some((k) => k.value === 0)) {
|
|
3079
|
+
const op = { keyframes: opKfs };
|
|
3080
|
+
if (loop !== void 0) op.loop = loop;
|
|
3081
|
+
animate.opacity = op;
|
|
3082
|
+
}
|
|
3083
|
+
out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
|
|
2809
3084
|
}
|
|
2810
3085
|
return out;
|
|
2811
3086
|
}
|
|
@@ -2849,7 +3124,7 @@ function toGroup(node, children, create) {
|
|
|
2849
3124
|
return create("g", gProps, children);
|
|
2850
3125
|
}
|
|
2851
3126
|
function materialiseGlyphText(node, opts) {
|
|
2852
|
-
if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength);
|
|
3127
|
+
if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
|
|
2853
3128
|
return materialiseGlyphTextHorizontal(node, opts);
|
|
2854
3129
|
}
|
|
2855
3130
|
function applyTextGlyphsEffect(node, fx, ctx) {
|
|
@@ -2860,12 +3135,12 @@ function applyTextGlyphsEffect(node, fx, ctx) {
|
|
|
2860
3135
|
}
|
|
2861
3136
|
return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
|
|
2862
3137
|
}
|
|
2863
|
-
function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength) {
|
|
3138
|
+
function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
|
|
2864
3139
|
if (!ctx.glyphs) {
|
|
2865
3140
|
ctx.warnings.push("textGlyphs: no definitions.glyphs");
|
|
2866
3141
|
return null;
|
|
2867
3142
|
}
|
|
2868
|
-
return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength);
|
|
3143
|
+
return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
|
|
2869
3144
|
}
|
|
2870
3145
|
|
|
2871
3146
|
// src/PxMotionPath.ts
|
|
@@ -3046,9 +3321,18 @@ function buildOutKfValue(prevV, nextV, p, translate, rotateDegFromAutoOrient, au
|
|
|
3046
3321
|
if (pv === void 0 && nv === void 0) continue;
|
|
3047
3322
|
value[k] = interpolatePart(pv, nv, p);
|
|
3048
3323
|
}
|
|
3049
|
-
if (rotateDegFromAutoOrient !== void 0)
|
|
3324
|
+
if (rotateDegFromAutoOrient !== void 0) {
|
|
3325
|
+
value.rotate = rotateDegFromAutoOrient + explicitRotateAt(prevV, nextV, p);
|
|
3326
|
+
}
|
|
3050
3327
|
return value;
|
|
3051
3328
|
}
|
|
3329
|
+
function explicitRotateAt(prevV, nextV, p) {
|
|
3330
|
+
const pv = typeof (prevV == null ? void 0 : prevV.rotate) === "number" ? prevV.rotate : void 0;
|
|
3331
|
+
const nv = typeof (nextV == null ? void 0 : nextV.rotate) === "number" ? nextV.rotate : void 0;
|
|
3332
|
+
if (pv === void 0 && nv === void 0) return 0;
|
|
3333
|
+
const r = interpolatePart(pv, nv, p);
|
|
3334
|
+
return typeof r === "number" ? r : 0;
|
|
3335
|
+
}
|
|
3052
3336
|
function derivAngleForFirstKf(kf0, kf1) {
|
|
3053
3337
|
const p0 = getKfTranslate(kf0);
|
|
3054
3338
|
const p1 = getKfTranslate(kf1);
|
|
@@ -3069,10 +3353,12 @@ function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos,
|
|
|
3069
3353
|
const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
|
|
3070
3354
|
const prevExit = lastV == null ? void 0 : lastV.rotate;
|
|
3071
3355
|
if (typeof prevExit !== "number") return;
|
|
3356
|
+
const boundaryV = getKfValueParts(prevKf);
|
|
3357
|
+
const prevExitTangent = prevExit - explicitRotateAt(boundaryV, boundaryV, 0);
|
|
3072
3358
|
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
3073
3359
|
const tanAtStart = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
|
|
3074
3360
|
const nextEntry = Math.atan2(tanAtStart[1], tanAtStart[0]) * 180 / Math.PI;
|
|
3075
|
-
const delta = wrappedAngleDelta(nextEntry,
|
|
3361
|
+
const delta = wrappedAngleDelta(nextEntry, prevExitTangent);
|
|
3076
3362
|
if (Math.abs(delta) <= rotationTol) return;
|
|
3077
3363
|
const dupValue = buildOutKfValue(
|
|
3078
3364
|
getKfValueParts(prevKf),
|
|
@@ -4271,18 +4557,17 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
4271
4557
|
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
4272
4558
|
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
4273
4559
|
if (!fx && !innerIdForContentRef) return node;
|
|
4274
|
-
const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient,
|
|
4560
|
+
const { transformation, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
|
|
4275
4561
|
const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
|
|
4276
4562
|
if (fx) delete node.effects;
|
|
4277
4563
|
let n = node;
|
|
4278
4564
|
let consumedByGlyphs = false;
|
|
4279
4565
|
if (text == null ? void 0 : text.useGlyphs) {
|
|
4280
|
-
if (
|
|
4281
|
-
const
|
|
4282
|
-
const
|
|
4283
|
-
const rawTL = textAlongPath.textLength;
|
|
4566
|
+
if (textPath) {
|
|
4567
|
+
const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
|
|
4568
|
+
const rawTL = textPath.textLength;
|
|
4284
4569
|
const textLength = typeof rawTL === "number" ? rawTL : rawTL && typeof rawTL === "object" ? typeof rawTL.value === "number" ? rawTL.value : Array.isArray(rawTL.keyframes) && rawTL.keyframes.length ? Number((_a = rawTL.keyframes[0]) == null ? void 0 : _a.value) : void 0 : void 0;
|
|
4285
|
-
const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD,
|
|
4570
|
+
const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textLength, textPath.pathOverflow);
|
|
4286
4571
|
if (glyphed) {
|
|
4287
4572
|
n = glyphed;
|
|
4288
4573
|
consumedByGlyphs = true;
|
|
@@ -4292,12 +4577,13 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
4292
4577
|
consumedByGlyphs = true;
|
|
4293
4578
|
}
|
|
4294
4579
|
}
|
|
4295
|
-
if (!consumedByGlyphs) n =
|
|
4580
|
+
if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
|
|
4296
4581
|
n = applyFillGradientEffect(n, fillGradient, ctx);
|
|
4297
4582
|
n = applyStrokeGradientEffect(n, strokeGradient, ctx);
|
|
4298
4583
|
n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
|
|
4299
4584
|
n = applyRepeaterEffect(n, repeater, ctx);
|
|
4300
4585
|
n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
|
|
4586
|
+
n = applyClipPathEffect(n, clipPath, ctx);
|
|
4301
4587
|
if (innerIdForContentRef) {
|
|
4302
4588
|
applyRefHref(n, cloneFx, ctx);
|
|
4303
4589
|
n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
|
|
@@ -4626,6 +4912,8 @@ function getNormalizedProps(props) {
|
|
|
4626
4912
|
function renderNode(node, defs) {
|
|
4627
4913
|
if (!node) return null;
|
|
4628
4914
|
const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
|
|
4915
|
+
const feFuncType = props.funcType;
|
|
4916
|
+
if (feFuncType !== void 0) delete props.funcType;
|
|
4629
4917
|
const nodeDefs = getDefs(node) || defs;
|
|
4630
4918
|
const resolvedStyle = resolveStyle2(style, nodeDefs);
|
|
4631
4919
|
let childElements;
|
|
@@ -4638,13 +4926,15 @@ function renderNode(node, defs) {
|
|
|
4638
4926
|
}
|
|
4639
4927
|
}
|
|
4640
4928
|
}
|
|
4641
|
-
|
|
4929
|
+
const element = createElement(
|
|
4642
4930
|
type || "g",
|
|
4643
4931
|
getNormalizedProps(props),
|
|
4644
4932
|
resolvedStyle,
|
|
4645
4933
|
childElements,
|
|
4646
4934
|
props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
|
|
4647
4935
|
);
|
|
4936
|
+
if (element && feFuncType !== void 0) element.setAttribute("type", feFuncType);
|
|
4937
|
+
return element;
|
|
4648
4938
|
}
|
|
4649
4939
|
|
|
4650
4940
|
// src/PxAnimatorTriggers.ts
|
|
@@ -4655,7 +4945,12 @@ function setupAnimationTriggers(api, config) {
|
|
|
4655
4945
|
console.warn("setupAnimationTriggers: No root element found for animation.");
|
|
4656
4946
|
return api;
|
|
4657
4947
|
}
|
|
4948
|
+
let reversed = false;
|
|
4658
4949
|
const start = () => {
|
|
4950
|
+
if (reversed) {
|
|
4951
|
+
reversed = false;
|
|
4952
|
+
api.setPlaybackRate(1);
|
|
4953
|
+
}
|
|
4659
4954
|
api.play();
|
|
4660
4955
|
};
|
|
4661
4956
|
const handleEndAction = () => {
|
|
@@ -4667,6 +4962,8 @@ function setupAnimationTriggers(api, config) {
|
|
|
4667
4962
|
api.cancel();
|
|
4668
4963
|
break;
|
|
4669
4964
|
case "reverse":
|
|
4965
|
+
reversed = true;
|
|
4966
|
+
api.setPlaybackRate(-1);
|
|
4670
4967
|
api.play();
|
|
4671
4968
|
break;
|
|
4672
4969
|
case "continue":
|
|
@@ -4729,6 +5026,7 @@ function getSelector(id) {
|
|
|
4729
5026
|
return "#" + id;
|
|
4730
5027
|
}
|
|
4731
5028
|
function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
5029
|
+
var _a;
|
|
4732
5030
|
const config = getAnimatorConfig(doc) || {};
|
|
4733
5031
|
const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
|
|
4734
5032
|
const _iterations = config.iterations;
|
|
@@ -4739,18 +5037,24 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4739
5037
|
const duration = +(config.duration || DEFAULT_DURATION_MS);
|
|
4740
5038
|
const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
|
|
4741
5039
|
const direction = config.direction || "normal";
|
|
5040
|
+
const fill = (_a = config.fill) != null ? _a : "forwards";
|
|
5041
|
+
const fillsForwards = fill === "forwards" || fill === "both";
|
|
5042
|
+
const fillsBackwards = fill === "backwards" || fill === "both";
|
|
4742
5043
|
let timerId = null;
|
|
4743
5044
|
let playing = false;
|
|
4744
|
-
let timeBeforeLastStartMs = config.delay || 0;
|
|
5045
|
+
let timeBeforeLastStartMs = -(config.delay || 0);
|
|
4745
5046
|
let lastStartedTs = 0;
|
|
4746
5047
|
let playbackRate = 1;
|
|
4747
5048
|
let finishCalled = false;
|
|
4748
5049
|
const frameRate = config.frameRate;
|
|
4749
5050
|
const minFrameIntervalMs = frameRate && frameRate > 0 ? 1e3 / frameRate : 0;
|
|
4750
5051
|
let lastRenderTs = 0;
|
|
4751
|
-
const
|
|
5052
|
+
const getRawAnimTime = () => {
|
|
4752
5053
|
const runningElapsed = lastStartedTs ? (Date.now() - lastStartedTs) * playbackRate : 0;
|
|
4753
|
-
|
|
5054
|
+
return timeBeforeLastStartMs + runningElapsed;
|
|
5055
|
+
};
|
|
5056
|
+
const getAnimCurrentTime = () => {
|
|
5057
|
+
let time = getRawAnimTime();
|
|
4754
5058
|
if (Number.isFinite(totalDuration) && time > totalDuration) time = totalDuration;
|
|
4755
5059
|
if (time < 0) time = 0;
|
|
4756
5060
|
return time;
|
|
@@ -4795,40 +5099,59 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4795
5099
|
}
|
|
4796
5100
|
}
|
|
4797
5101
|
const tick = () => {
|
|
4798
|
-
var
|
|
5102
|
+
var _a2, _b;
|
|
4799
5103
|
if (!adapter.isConnected()) {
|
|
4800
5104
|
pauseAnim();
|
|
4801
5105
|
return;
|
|
4802
5106
|
}
|
|
4803
5107
|
const currentTime = getAnimCurrentTime();
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
if (
|
|
4807
|
-
|
|
4808
|
-
}
|
|
4809
|
-
lastRenderTs = now;
|
|
4810
|
-
}
|
|
4811
|
-
if (duration <= 0) {
|
|
5108
|
+
const rawTime = getRawAnimTime();
|
|
5109
|
+
if (rawTime < 0 && playbackRate > 0) {
|
|
5110
|
+
if (fillsBackwards) renderFrame(0);
|
|
5111
|
+
return;
|
|
4812
5112
|
}
|
|
4813
|
-
if (
|
|
4814
|
-
|
|
5113
|
+
if (playbackRate < 0 && rawTime <= 0) {
|
|
5114
|
+
pauseAnim();
|
|
5115
|
+
renderFrame(0);
|
|
4815
5116
|
if (!finishCalled) {
|
|
4816
5117
|
finishCalled = true;
|
|
4817
|
-
(
|
|
5118
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
4818
5119
|
}
|
|
5120
|
+
return;
|
|
5121
|
+
}
|
|
5122
|
+
if (playbackRate > 0 && totalDuration && Number.isFinite(totalDuration) && currentTime >= totalDuration) {
|
|
4819
5123
|
pauseAnim();
|
|
5124
|
+
renderFrame(fillsForwards ? totalDuration : 0);
|
|
5125
|
+
if (!finishCalled) {
|
|
5126
|
+
finishCalled = true;
|
|
5127
|
+
(_b = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _b.call(callbacks);
|
|
5128
|
+
}
|
|
4820
5129
|
return;
|
|
4821
5130
|
}
|
|
5131
|
+
if (minFrameIntervalMs > 0) {
|
|
5132
|
+
const now = Date.now();
|
|
5133
|
+
if (lastRenderTs && now - lastRenderTs < minFrameIntervalMs) {
|
|
5134
|
+
return;
|
|
5135
|
+
}
|
|
5136
|
+
lastRenderTs = now;
|
|
5137
|
+
}
|
|
4822
5138
|
renderFrame(currentTime);
|
|
4823
5139
|
};
|
|
4824
5140
|
if (config.delay) {
|
|
4825
|
-
|
|
5141
|
+
if (config.delay < 0) {
|
|
5142
|
+
renderFrame(getAnimCurrentTime());
|
|
5143
|
+
} else if (fillsBackwards) {
|
|
5144
|
+
renderFrame(0);
|
|
5145
|
+
}
|
|
4826
5146
|
}
|
|
4827
5147
|
const _isPlaying = () => {
|
|
4828
5148
|
if (!playing) return false;
|
|
4829
5149
|
if (!adapter.isConnected()) {
|
|
4830
5150
|
return false;
|
|
4831
5151
|
}
|
|
5152
|
+
if (playbackRate < 0) {
|
|
5153
|
+
return getRawAnimTime() > 0;
|
|
5154
|
+
}
|
|
4832
5155
|
if (Number.isFinite(totalDuration) && getAnimCurrentTime() >= totalDuration) return false;
|
|
4833
5156
|
return true;
|
|
4834
5157
|
};
|
|
@@ -4848,37 +5171,53 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4848
5171
|
};
|
|
4849
5172
|
const startAnim = () => {
|
|
4850
5173
|
if (playing) return;
|
|
4851
|
-
if (
|
|
4852
|
-
timeBeforeLastStartMs
|
|
4853
|
-
|
|
5174
|
+
if (playbackRate >= 0) {
|
|
5175
|
+
if (Number.isFinite(totalDuration) && timeBeforeLastStartMs >= totalDuration) {
|
|
5176
|
+
timeBeforeLastStartMs = 0;
|
|
5177
|
+
}
|
|
5178
|
+
} else {
|
|
5179
|
+
if (timeBeforeLastStartMs <= 0) {
|
|
5180
|
+
if (!Number.isFinite(totalDuration)) {
|
|
5181
|
+
console.warn("play: cannot start reverse playback of an infinite animation from time 0");
|
|
5182
|
+
return;
|
|
5183
|
+
}
|
|
5184
|
+
timeBeforeLastStartMs = totalDuration;
|
|
5185
|
+
}
|
|
4854
5186
|
}
|
|
5187
|
+
finishCalled = false;
|
|
4855
5188
|
playing = true;
|
|
4856
5189
|
lastStartedTs = Date.now();
|
|
4857
5190
|
loopAnim(true);
|
|
4858
5191
|
};
|
|
4859
5192
|
const pauseAnim = () => {
|
|
4860
5193
|
if (!playing) return;
|
|
4861
|
-
|
|
5194
|
+
let raw = getRawAnimTime();
|
|
5195
|
+
if (Number.isFinite(totalDuration) && raw > totalDuration) raw = totalDuration;
|
|
5196
|
+
timeBeforeLastStartMs = raw;
|
|
4862
5197
|
lastStartedTs = 0;
|
|
4863
5198
|
playing = false;
|
|
4864
5199
|
if (timerId !== null) {
|
|
4865
5200
|
cancelAnimationFrame(timerId);
|
|
4866
5201
|
timerId = null;
|
|
4867
5202
|
}
|
|
4868
|
-
|
|
5203
|
+
if (raw >= 0) {
|
|
5204
|
+
renderFrame(raw);
|
|
5205
|
+
} else if (fillsBackwards) {
|
|
5206
|
+
renderFrame(0);
|
|
5207
|
+
}
|
|
4869
5208
|
};
|
|
4870
5209
|
const cancelAnim = () => {
|
|
4871
|
-
var
|
|
5210
|
+
var _a2;
|
|
4872
5211
|
pauseAnim();
|
|
4873
5212
|
timeBeforeLastStartMs = 0;
|
|
4874
5213
|
lastStartedTs = 0;
|
|
4875
5214
|
playing = false;
|
|
4876
5215
|
finishCalled = false;
|
|
4877
5216
|
renderFrame(timeBeforeLastStartMs);
|
|
4878
|
-
(
|
|
5217
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
4879
5218
|
};
|
|
4880
5219
|
const finishAnim = (callOnFinish = true) => {
|
|
4881
|
-
var
|
|
5220
|
+
var _a2;
|
|
4882
5221
|
if (Number.isFinite(totalDuration)) {
|
|
4883
5222
|
timeBeforeLastStartMs = totalDuration;
|
|
4884
5223
|
} else {
|
|
@@ -4886,10 +5225,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4886
5225
|
}
|
|
4887
5226
|
lastStartedTs = 0;
|
|
4888
5227
|
playing = false;
|
|
4889
|
-
|
|
5228
|
+
if (timerId !== null) {
|
|
5229
|
+
cancelAnimationFrame(timerId);
|
|
5230
|
+
timerId = null;
|
|
5231
|
+
}
|
|
5232
|
+
renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
|
|
4890
5233
|
if (callOnFinish && !finishCalled) {
|
|
4891
5234
|
finishCalled = true;
|
|
4892
|
-
(
|
|
5235
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
4893
5236
|
}
|
|
4894
5237
|
};
|
|
4895
5238
|
const api = {
|
|
@@ -4899,14 +5242,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4899
5242
|
return _isPlaying();
|
|
4900
5243
|
},
|
|
4901
5244
|
"play": () => {
|
|
4902
|
-
var
|
|
5245
|
+
var _a2;
|
|
4903
5246
|
startAnim();
|
|
4904
|
-
(
|
|
5247
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
4905
5248
|
},
|
|
4906
5249
|
"pause": () => {
|
|
4907
|
-
var
|
|
5250
|
+
var _a2;
|
|
4908
5251
|
pauseAnim();
|
|
4909
|
-
(
|
|
5252
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
|
|
4910
5253
|
},
|
|
4911
5254
|
"cancel": () => {
|
|
4912
5255
|
cancelAnim();
|
|
@@ -4919,7 +5262,9 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4919
5262
|
console.warn("setPlaybackRate: rate must be finite and non-zero");
|
|
4920
5263
|
return;
|
|
4921
5264
|
}
|
|
4922
|
-
|
|
5265
|
+
let current = getRawAnimTime();
|
|
5266
|
+
if (Number.isFinite(totalDuration) && current > totalDuration) current = totalDuration;
|
|
5267
|
+
if (rate < 0 !== playbackRate < 0) finishCalled = false;
|
|
4923
5268
|
playbackRate = rate;
|
|
4924
5269
|
timeBeforeLastStartMs = current;
|
|
4925
5270
|
if (playing) lastStartedTs = Date.now();
|
|
@@ -4932,10 +5277,13 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4932
5277
|
if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
|
|
4933
5278
|
timeBeforeLastStartMs = newTime;
|
|
4934
5279
|
if (playing) lastStartedTs = Date.now();
|
|
5280
|
+
if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
|
|
4935
5281
|
renderFrame(getAnimCurrentTime());
|
|
4936
5282
|
},
|
|
4937
5283
|
"destroy": () => {
|
|
5284
|
+
var _a2;
|
|
4938
5285
|
api.cancel();
|
|
5286
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
4939
5287
|
}
|
|
4940
5288
|
};
|
|
4941
5289
|
return api;
|
|
@@ -5100,6 +5448,8 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5100
5448
|
if (typeof _iterations === "number") iterations = _iterations;
|
|
5101
5449
|
if (_iterations === "infinite") iterations = Infinity;
|
|
5102
5450
|
const unsupportedSet = /* @__PURE__ */ new Set();
|
|
5451
|
+
let finishNotified = false;
|
|
5452
|
+
let removeCalled = false;
|
|
5103
5453
|
if (!(bindings == null ? void 0 : bindings.length)) {
|
|
5104
5454
|
console.warn("createWebApiAnimator: No animation bindings defined");
|
|
5105
5455
|
}
|
|
@@ -5116,7 +5466,11 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5116
5466
|
}
|
|
5117
5467
|
const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
|
|
5118
5468
|
const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
|
|
5119
|
-
|
|
5469
|
+
let seekPosition;
|
|
5470
|
+
if (config.delay && config.delay < 0 && config.duration) {
|
|
5471
|
+
const rawSeek = -config.delay;
|
|
5472
|
+
seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : 1));
|
|
5473
|
+
}
|
|
5120
5474
|
const effectOptions = {
|
|
5121
5475
|
duration: config.duration,
|
|
5122
5476
|
delay: positiveDelay,
|
|
@@ -5137,13 +5491,17 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5137
5491
|
const anim = new Animation(effect, document.timeline);
|
|
5138
5492
|
if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
|
|
5139
5493
|
var _a2;
|
|
5140
|
-
|
|
5494
|
+
if (finishNotified) return;
|
|
5495
|
+
finishNotified = true;
|
|
5496
|
+
(_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
5141
5497
|
};
|
|
5142
5498
|
if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
|
|
5143
5499
|
var _a2;
|
|
5144
|
-
|
|
5500
|
+
if (removeCalled) return;
|
|
5501
|
+
removeCalled = true;
|
|
5502
|
+
(_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
5145
5503
|
};
|
|
5146
|
-
if (seekPosition) {
|
|
5504
|
+
if (seekPosition !== void 0) {
|
|
5147
5505
|
anim.currentTime = seekPosition;
|
|
5148
5506
|
}
|
|
5149
5507
|
animations.push(anim);
|
|
@@ -5167,6 +5525,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5167
5525
|
},
|
|
5168
5526
|
"play": () => {
|
|
5169
5527
|
var _a2;
|
|
5528
|
+
finishNotified = false;
|
|
5170
5529
|
animations.forEach((a) => a.play());
|
|
5171
5530
|
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
5172
5531
|
},
|
|
@@ -5177,6 +5536,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5177
5536
|
},
|
|
5178
5537
|
"cancel": () => {
|
|
5179
5538
|
var _a2;
|
|
5539
|
+
finishNotified = false;
|
|
5180
5540
|
animations.forEach((a) => a.cancel());
|
|
5181
5541
|
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
5182
5542
|
},
|
|
@@ -5206,13 +5566,19 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5206
5566
|
return res !== null ? +res : null;
|
|
5207
5567
|
},
|
|
5208
5568
|
"setCurrentTime": (time) => {
|
|
5569
|
+
finishNotified = false;
|
|
5209
5570
|
animations.forEach((a) => {
|
|
5210
5571
|
a.currentTime = time;
|
|
5211
5572
|
});
|
|
5212
5573
|
},
|
|
5213
5574
|
"destroy": () => {
|
|
5575
|
+
var _a2;
|
|
5214
5576
|
api.cancel();
|
|
5215
5577
|
animations.splice(0, animations.length);
|
|
5578
|
+
if (!removeCalled) {
|
|
5579
|
+
removeCalled = true;
|
|
5580
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
5581
|
+
}
|
|
5216
5582
|
}
|
|
5217
5583
|
};
|
|
5218
5584
|
if (config.trigger) {
|
|
@@ -5356,7 +5722,6 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
|
5356
5722
|
const effectsWarnings = validateNodeEffects(doc);
|
|
5357
5723
|
for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
|
|
5358
5724
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
5359
|
-
animatorConfig.debug = true;
|
|
5360
5725
|
const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
|
|
5361
5726
|
doc = materialiseAllInTree(doc, engine);
|
|
5362
5727
|
let rootElement = null;
|
|
@@ -5385,37 +5750,55 @@ function createAnimator(options) {
|
|
|
5385
5750
|
return createAnimatorImpl(data, adapter, callbacks, container);
|
|
5386
5751
|
}
|
|
5387
5752
|
let animator = null;
|
|
5753
|
+
let pending = [];
|
|
5754
|
+
let destroyed = false;
|
|
5755
|
+
const enqueue = (call) => {
|
|
5756
|
+
if (animator) {
|
|
5757
|
+
call(animator);
|
|
5758
|
+
} else if (pending) {
|
|
5759
|
+
pending.push(call);
|
|
5760
|
+
}
|
|
5761
|
+
};
|
|
5388
5762
|
fetch(src).then((res) => res.json()).then((json) => {
|
|
5763
|
+
if (destroyed) return;
|
|
5389
5764
|
if (isPxElementFileFormat(json)) {
|
|
5390
5765
|
animator = createAnimatorImpl(json, adapter, callbacks, container);
|
|
5766
|
+
const queued = pending;
|
|
5767
|
+
pending = null;
|
|
5768
|
+
queued == null ? void 0 : queued.forEach((call) => call(animator));
|
|
5391
5769
|
} else {
|
|
5392
|
-
console.error(
|
|
5770
|
+
console.error('createAnimator: invalid animation document format at "' + src + '"');
|
|
5393
5771
|
}
|
|
5772
|
+
}).catch((err) => {
|
|
5773
|
+
pending = null;
|
|
5774
|
+
console.error('createAnimator: failed to load "' + src + '"', err);
|
|
5394
5775
|
});
|
|
5395
5776
|
return {
|
|
5396
5777
|
"isReady": () => !!animator,
|
|
5397
5778
|
"getRootElement": () => animator ? animator.getRootElement() : null,
|
|
5398
5779
|
"isPlaying": () => (animator == null ? void 0 : animator.isPlaying()) || false,
|
|
5399
5780
|
"play": () => {
|
|
5400
|
-
|
|
5781
|
+
enqueue((api) => api.play());
|
|
5401
5782
|
},
|
|
5402
5783
|
"pause": () => {
|
|
5403
|
-
|
|
5784
|
+
enqueue((api) => api.pause());
|
|
5404
5785
|
},
|
|
5405
5786
|
"cancel": () => {
|
|
5406
|
-
|
|
5787
|
+
enqueue((api) => api.cancel());
|
|
5407
5788
|
},
|
|
5408
5789
|
"finish": () => {
|
|
5409
|
-
|
|
5790
|
+
enqueue((api) => api.finish());
|
|
5410
5791
|
},
|
|
5411
5792
|
"setPlaybackRate": (rate) => {
|
|
5412
|
-
|
|
5793
|
+
enqueue((api) => api.setPlaybackRate(rate));
|
|
5413
5794
|
},
|
|
5414
|
-
"getCurrentTime": () =>
|
|
5795
|
+
"getCurrentTime": () => animator ? animator.getCurrentTime() : null,
|
|
5415
5796
|
"setCurrentTime": (time) => {
|
|
5416
|
-
|
|
5797
|
+
enqueue((api) => api.setCurrentTime(time));
|
|
5417
5798
|
},
|
|
5418
5799
|
"destroy": () => {
|
|
5800
|
+
destroyed = true;
|
|
5801
|
+
pending = null;
|
|
5419
5802
|
animator == null ? void 0 : animator.destroy();
|
|
5420
5803
|
}
|
|
5421
5804
|
};
|
|
@@ -5679,8 +6062,8 @@ export {
|
|
|
5679
6062
|
PxRetimeEffectSchema,
|
|
5680
6063
|
PxStrokeGradientEffectSchema,
|
|
5681
6064
|
PxSvgNodeExtra,
|
|
5682
|
-
PxTextAlongPathEffectSchema,
|
|
5683
6065
|
PxTextEffectSchema,
|
|
6066
|
+
PxTextPathEffectSchema,
|
|
5684
6067
|
PxTransformPartsSchema,
|
|
5685
6068
|
PxTransformValueSchema,
|
|
5686
6069
|
PxTransformationEffectSchema,
|
|
@@ -5696,10 +6079,12 @@ export {
|
|
|
5696
6079
|
createAnimatorImpl,
|
|
5697
6080
|
createBasicFrameLoopAnimator,
|
|
5698
6081
|
createFrameLoopAnimator,
|
|
6082
|
+
createPathSampler,
|
|
5699
6083
|
createWebApiAnimator,
|
|
5700
6084
|
describeSchema,
|
|
5701
6085
|
diffInEffect,
|
|
5702
6086
|
evaluateMotionPathSegment,
|
|
6087
|
+
extendedPathForBrowser,
|
|
5703
6088
|
generateNewIds,
|
|
5704
6089
|
getAnimatorConfig,
|
|
5705
6090
|
getBindings,
|
|
@@ -5709,6 +6094,7 @@ export {
|
|
|
5709
6094
|
isPxElementFileFormat,
|
|
5710
6095
|
isPxElementFileFormatDeep,
|
|
5711
6096
|
jsonElementFactory,
|
|
6097
|
+
layoutGlyphTextChars,
|
|
5712
6098
|
loadTagAnimators,
|
|
5713
6099
|
materialiseAllInTree,
|
|
5714
6100
|
materialiseAnimatedUseInstances,
|
|
@@ -5725,6 +6111,7 @@ export {
|
|
|
5725
6111
|
renderNode,
|
|
5726
6112
|
schemaKeys,
|
|
5727
6113
|
setupAnimationTriggers,
|
|
6114
|
+
shiftAnimatable,
|
|
5728
6115
|
toRGBA,
|
|
5729
6116
|
validateNodeEffects,
|
|
5730
6117
|
visualModelAt
|