@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.cjs
CHANGED
|
@@ -83,8 +83,8 @@ __export(index_exports, {
|
|
|
83
83
|
PxRetimeEffectSchema: () => PxRetimeEffectSchema,
|
|
84
84
|
PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
|
|
85
85
|
PxSvgNodeExtra: () => PxSvgNodeExtra,
|
|
86
|
-
PxTextAlongPathEffectSchema: () => PxTextAlongPathEffectSchema,
|
|
87
86
|
PxTextEffectSchema: () => PxTextEffectSchema,
|
|
87
|
+
PxTextPathEffectSchema: () => PxTextPathEffectSchema,
|
|
88
88
|
PxTransformPartsSchema: () => PxTransformPartsSchema,
|
|
89
89
|
PxTransformValueSchema: () => PxTransformValueSchema,
|
|
90
90
|
PxTransformationEffectSchema: () => PxTransformationEffectSchema,
|
|
@@ -100,10 +100,12 @@ __export(index_exports, {
|
|
|
100
100
|
createAnimatorImpl: () => createAnimatorImpl,
|
|
101
101
|
createBasicFrameLoopAnimator: () => createBasicFrameLoopAnimator,
|
|
102
102
|
createFrameLoopAnimator: () => createFrameLoopAnimator,
|
|
103
|
+
createPathSampler: () => createPathSampler,
|
|
103
104
|
createWebApiAnimator: () => createWebApiAnimator,
|
|
104
105
|
describeSchema: () => describeSchema,
|
|
105
106
|
diffInEffect: () => diffInEffect,
|
|
106
107
|
evaluateMotionPathSegment: () => evaluateMotionPathSegment,
|
|
108
|
+
extendedPathForBrowser: () => extendedPathForBrowser,
|
|
107
109
|
generateNewIds: () => generateNewIds,
|
|
108
110
|
getAnimatorConfig: () => getAnimatorConfig,
|
|
109
111
|
getBindings: () => getBindings,
|
|
@@ -113,6 +115,7 @@ __export(index_exports, {
|
|
|
113
115
|
isPxElementFileFormat: () => isPxElementFileFormat,
|
|
114
116
|
isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
|
|
115
117
|
jsonElementFactory: () => jsonElementFactory,
|
|
118
|
+
layoutGlyphTextChars: () => layoutGlyphTextChars,
|
|
116
119
|
loadTagAnimators: () => loadTagAnimators,
|
|
117
120
|
materialiseAllInTree: () => materialiseAllInTree,
|
|
118
121
|
materialiseAnimatedUseInstances: () => materialiseAnimatedUseInstances,
|
|
@@ -129,6 +132,7 @@ __export(index_exports, {
|
|
|
129
132
|
renderNode: () => renderNode,
|
|
130
133
|
schemaKeys: () => schemaKeys,
|
|
131
134
|
setupAnimationTriggers: () => setupAnimationTriggers,
|
|
135
|
+
shiftAnimatable: () => shiftAnimatable,
|
|
132
136
|
toRGBA: () => toRGBA,
|
|
133
137
|
validateNodeEffects: () => validateNodeEffects,
|
|
134
138
|
visualModelAt: () => visualModelAt
|
|
@@ -1088,6 +1092,10 @@ var PxMaskedByEffectSchema = implementsInterface()(px.object({
|
|
|
1088
1092
|
maskUnits: px.string().optional(),
|
|
1089
1093
|
maskContentUnits: px.string().optional()
|
|
1090
1094
|
}));
|
|
1095
|
+
var PxClipPathEffectSchema = implementsInterface()(px.object({
|
|
1096
|
+
d: px.string().optional(),
|
|
1097
|
+
animate: PxPropertyAnimationSchema.optional()
|
|
1098
|
+
}));
|
|
1091
1099
|
var PxTrimPathEffectSchema = implementsInterface()(px.object({
|
|
1092
1100
|
offset: PxAnimatableNumberSchema.optional(),
|
|
1093
1101
|
range: PxAnimatableVec2Schema.optional(),
|
|
@@ -1139,8 +1147,9 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
|
1139
1147
|
gradientTransform: px.string().optional()
|
|
1140
1148
|
}));
|
|
1141
1149
|
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
1142
|
-
var
|
|
1143
|
-
|
|
1150
|
+
var PxTextPathEffectSchema = implementsInterface()(px.object({
|
|
1151
|
+
path: px.string(),
|
|
1152
|
+
pathOverflow: px.string().optional(),
|
|
1144
1153
|
lengthAdjust: px.string().optional(),
|
|
1145
1154
|
method: px.string().optional(),
|
|
1146
1155
|
spacing: px.string().optional(),
|
|
@@ -1154,12 +1163,13 @@ var PxEffectsSchema = implementsInterface()(px.object({
|
|
|
1154
1163
|
transformation: PxTransformationEffectSchema.optional(),
|
|
1155
1164
|
repeater: PxRepeaterEffectSchema.optional(),
|
|
1156
1165
|
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1166
|
+
clipPath: PxClipPathEffectSchema.optional(),
|
|
1157
1167
|
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1158
1168
|
clone: PxCloneEffectSchema.optional(),
|
|
1159
1169
|
isCombinedShape: px.boolean().optional(),
|
|
1160
1170
|
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
1161
1171
|
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
1162
|
-
|
|
1172
|
+
textPath: PxTextPathEffectSchema.optional(),
|
|
1163
1173
|
text: PxTextEffectSchema.optional()
|
|
1164
1174
|
}));
|
|
1165
1175
|
function validateNodeEffects(root, opts) {
|
|
@@ -1460,6 +1470,17 @@ function formatOffset(o) {
|
|
|
1460
1470
|
return pct + "%";
|
|
1461
1471
|
}
|
|
1462
1472
|
|
|
1473
|
+
// src/effects/clipPathEffect.ts
|
|
1474
|
+
function applyClipPathEffect(node, fx, ctx) {
|
|
1475
|
+
if (!fx || !fx.d && !fx.animate) return node;
|
|
1476
|
+
const clipId = genId(ctx, "clip");
|
|
1477
|
+
const pathChild = { type: "path", d: fx.d };
|
|
1478
|
+
if (fx.animate) pathChild.animate = { d: fx.animate };
|
|
1479
|
+
ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
|
|
1480
|
+
node.clipPath = "url(#" + clipId + ")";
|
|
1481
|
+
return node;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1463
1484
|
// src/effects/maskedByEffect.ts
|
|
1464
1485
|
function applyMaskedByEffect(node, fx, transformation, ctx) {
|
|
1465
1486
|
if (!fx) return node;
|
|
@@ -1902,6 +1923,9 @@ function synthesiseScale(raw, i) {
|
|
|
1902
1923
|
var RETIME_MATERIALISATION_MODE_INLINE_G = false;
|
|
1903
1924
|
function asRetime(r) {
|
|
1904
1925
|
var _a, _b;
|
|
1926
|
+
if (r.timeCrop) {
|
|
1927
|
+
console.warn("retime: `timeCrop` is not supported yet and will be ignored");
|
|
1928
|
+
}
|
|
1905
1929
|
return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
|
|
1906
1930
|
}
|
|
1907
1931
|
function concatRetime(child, parent) {
|
|
@@ -2032,103 +2056,6 @@ function remapKeyframeTimesOnly(node, start, stretch) {
|
|
|
2032
2056
|
}
|
|
2033
2057
|
}
|
|
2034
2058
|
|
|
2035
|
-
// src/effects/textAlongPathEffect.ts
|
|
2036
|
-
function applyTextAlongPathEffect(node, fx, _ctx) {
|
|
2037
|
-
var _a;
|
|
2038
|
-
if (!fx) return node;
|
|
2039
|
-
const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
|
|
2040
|
-
const textPath = {
|
|
2041
|
-
type: "textPath",
|
|
2042
|
-
href,
|
|
2043
|
-
children: (_a = node.children) != null ? _a : []
|
|
2044
|
-
};
|
|
2045
|
-
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
2046
|
-
if (fx.method !== void 0) textPath.method = fx.method;
|
|
2047
|
-
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
2048
|
-
applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
|
|
2049
|
-
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
2050
|
-
node.children = [textPath];
|
|
2051
|
-
return node;
|
|
2052
|
-
}
|
|
2053
|
-
function applyAnimatableNumber(node, attrName, raw) {
|
|
2054
|
-
if (raw === void 0 || raw === null) return;
|
|
2055
|
-
if (typeof raw === "number") {
|
|
2056
|
-
node[attrName] = String(raw);
|
|
2057
|
-
return;
|
|
2058
|
-
}
|
|
2059
|
-
if (typeof raw === "object" && raw !== null) {
|
|
2060
|
-
const obj = raw;
|
|
2061
|
-
if (Array.isArray(obj.keyframes)) {
|
|
2062
|
-
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
2063
|
-
const animate = __spreadValues({}, prevAnimate || {});
|
|
2064
|
-
const block = { keyframes: obj.keyframes };
|
|
2065
|
-
if (obj.loop !== void 0) block.loop = obj.loop;
|
|
2066
|
-
animate[attrName] = block;
|
|
2067
|
-
node.animate = animate;
|
|
2068
|
-
return;
|
|
2069
|
-
}
|
|
2070
|
-
if (typeof obj.value === "number") {
|
|
2071
|
-
node[attrName] = String(obj.value);
|
|
2072
|
-
return;
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
// src/effects/elementFactory.ts
|
|
2078
|
-
var jsonElementFactory = (type, props, children) => {
|
|
2079
|
-
const node = { type };
|
|
2080
|
-
for (const k in props) if (props[k] !== void 0) node[k] = props[k];
|
|
2081
|
-
const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
|
|
2082
|
-
if (arr.length) node.children = arr;
|
|
2083
|
-
return node;
|
|
2084
|
-
};
|
|
2085
|
-
|
|
2086
|
-
// src/effects/glyphPathBake.ts
|
|
2087
|
-
function fmt(v, decimals) {
|
|
2088
|
-
return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
|
|
2089
|
-
}
|
|
2090
|
-
function pack(nums, decimals) {
|
|
2091
|
-
let s = "";
|
|
2092
|
-
for (let i = 0; i < nums.length; i++) {
|
|
2093
|
-
const str2 = fmt(nums[i], decimals);
|
|
2094
|
-
if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
|
|
2095
|
-
s += str2;
|
|
2096
|
-
}
|
|
2097
|
-
return s;
|
|
2098
|
-
}
|
|
2099
|
-
function apply(m, x, y) {
|
|
2100
|
-
return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
2101
|
-
}
|
|
2102
|
-
var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
|
|
2103
|
-
function transformPathData(d, m, decimals = 2) {
|
|
2104
|
-
const tokens = [];
|
|
2105
|
-
let match;
|
|
2106
|
-
TOKEN_RE.lastIndex = 0;
|
|
2107
|
-
while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
|
|
2108
|
-
let out = "";
|
|
2109
|
-
let i = 0;
|
|
2110
|
-
const num2 = () => parseFloat(tokens[i++]);
|
|
2111
|
-
while (i < tokens.length) {
|
|
2112
|
-
const cmd = tokens[i++];
|
|
2113
|
-
if (cmd === "M" || cmd === "L") {
|
|
2114
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2115
|
-
out += cmd + pack([x, y], decimals);
|
|
2116
|
-
} else if (cmd === "C") {
|
|
2117
|
-
const [x1, y1] = apply(m, num2(), num2());
|
|
2118
|
-
const [x2, y2] = apply(m, num2(), num2());
|
|
2119
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2120
|
-
out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
|
|
2121
|
-
} else if (cmd === "Q") {
|
|
2122
|
-
const [x1, y1] = apply(m, num2(), num2());
|
|
2123
|
-
const [x, y] = apply(m, num2(), num2());
|
|
2124
|
-
out += "Q" + pack([x1, y1, x, y], decimals);
|
|
2125
|
-
} else if (cmd === "Z" || cmd === "z") {
|
|
2126
|
-
out += "Z";
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
return out;
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
2059
|
// src/PxAnimatorUtil.ts
|
|
2133
2060
|
function bezierToSvgPath(path) {
|
|
2134
2061
|
var _a, _b, _c, _d;
|
|
@@ -2417,6 +2344,8 @@ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
|
2417
2344
|
// Filter
|
|
2418
2345
|
"filterUnits",
|
|
2419
2346
|
"primitiveUnits",
|
|
2347
|
+
"tableValues",
|
|
2348
|
+
// feFuncR/G/B/A transfer table (type="table")
|
|
2420
2349
|
"stdDeviation",
|
|
2421
2350
|
"baseFrequency",
|
|
2422
2351
|
"numOctaves",
|
|
@@ -2673,7 +2602,11 @@ function createPathSampler(d) {
|
|
|
2673
2602
|
};
|
|
2674
2603
|
return {
|
|
2675
2604
|
totalLength,
|
|
2605
|
+
closed,
|
|
2676
2606
|
sampleAtDistance(dist) {
|
|
2607
|
+
if (closed && totalLength > 0 && (dist < 0 || dist > totalLength)) {
|
|
2608
|
+
return sampleOn((dist % totalLength + totalLength) % totalLength);
|
|
2609
|
+
}
|
|
2677
2610
|
if (!closed && (dist < 0 || dist > totalLength)) {
|
|
2678
2611
|
const edge = dist < 0 ? 0 : totalLength;
|
|
2679
2612
|
const p = sampleOn(edge);
|
|
@@ -2685,6 +2618,173 @@ function createPathSampler(d) {
|
|
|
2685
2618
|
};
|
|
2686
2619
|
}
|
|
2687
2620
|
|
|
2621
|
+
// src/effects/textPathEffect.ts
|
|
2622
|
+
var EXTEND_MARGIN_FRAC = 0.15;
|
|
2623
|
+
function numRange(v) {
|
|
2624
|
+
if (typeof v === "number") return { min: v, max: v };
|
|
2625
|
+
if (v && typeof v === "object") {
|
|
2626
|
+
const o = v;
|
|
2627
|
+
if (typeof o.value === "number") return { min: o.value, max: o.value };
|
|
2628
|
+
if (Array.isArray(o.keyframes) && o.keyframes.length) {
|
|
2629
|
+
const vals = o.keyframes.map((k) => Number(k.value) || 0);
|
|
2630
|
+
return { min: Math.min(...vals), max: Math.max(...vals) };
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
return { min: 0, max: 0 };
|
|
2634
|
+
}
|
|
2635
|
+
function estimateTextAdvance(node) {
|
|
2636
|
+
let chars = 0, maxFont = 16;
|
|
2637
|
+
const walk = (el) => {
|
|
2638
|
+
var _a, _b;
|
|
2639
|
+
const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
|
|
2640
|
+
if (fs) maxFont = Math.max(maxFont, fs);
|
|
2641
|
+
const t = (_b = el.text) != null ? _b : el.textContent;
|
|
2642
|
+
if (typeof t === "string") chars += t.length;
|
|
2643
|
+
if (el.children) for (const c of el.children) walk(c);
|
|
2644
|
+
};
|
|
2645
|
+
walk(node);
|
|
2646
|
+
return chars * maxFont;
|
|
2647
|
+
}
|
|
2648
|
+
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
2649
|
+
function shiftAnimatable(v, by) {
|
|
2650
|
+
if (!by || v === void 0 || v === null) return v;
|
|
2651
|
+
if (typeof v === "number") return v + by;
|
|
2652
|
+
const o = v;
|
|
2653
|
+
if (typeof o.value === "number") return __spreadProps(__spreadValues({}, o), { value: o.value + by });
|
|
2654
|
+
if (Array.isArray(o.keyframes)) return __spreadProps(__spreadValues({}, o), { keyframes: o.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by })) });
|
|
2655
|
+
return v;
|
|
2656
|
+
}
|
|
2657
|
+
function extendedPathForBrowser(pathD, opts) {
|
|
2658
|
+
var _a;
|
|
2659
|
+
if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
|
|
2660
|
+
const sampler = createPathSampler(pathD);
|
|
2661
|
+
if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
|
|
2662
|
+
const L = sampler.totalLength;
|
|
2663
|
+
const margin = EXTEND_MARGIN_FRAC * L;
|
|
2664
|
+
const so = numRange(opts.startOffset);
|
|
2665
|
+
const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
|
|
2666
|
+
const startOverflow = Math.max(0, -so.min);
|
|
2667
|
+
const endOverflow = Math.max(0, so.max + runWidth - L);
|
|
2668
|
+
const startExt = startOverflow > 0 ? startOverflow + margin : 0;
|
|
2669
|
+
const endExt = endOverflow > 0 ? endOverflow + margin : 0;
|
|
2670
|
+
if (endExt <= 0 && startExt <= 0) return { d: pathD, startShift: 0 };
|
|
2671
|
+
const s = sampler.sampleAtDistance(0);
|
|
2672
|
+
const e = sampler.sampleAtDistance(L);
|
|
2673
|
+
let d = pathD;
|
|
2674
|
+
if (startExt > 0) {
|
|
2675
|
+
const sx = s.x - Math.cos(s.angle) * startExt, sy = s.y - Math.sin(s.angle) * startExt;
|
|
2676
|
+
const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
|
|
2677
|
+
d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
|
|
2678
|
+
}
|
|
2679
|
+
if (endExt > 0) {
|
|
2680
|
+
const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
|
|
2681
|
+
d += "L" + r3(ex) + "," + r3(ey);
|
|
2682
|
+
}
|
|
2683
|
+
return { d, startShift: startExt };
|
|
2684
|
+
}
|
|
2685
|
+
function applyTextPathEffect(node, fx, ctx) {
|
|
2686
|
+
var _a;
|
|
2687
|
+
if (!fx || typeof fx.path !== "string" || !fx.path) return node;
|
|
2688
|
+
const pathId = genId(ctx, "tpath");
|
|
2689
|
+
const { d, startShift } = extendedPathForBrowser(fx.path, {
|
|
2690
|
+
pathOverflow: fx.pathOverflow,
|
|
2691
|
+
startOffset: fx.startOffset,
|
|
2692
|
+
textLength: fx.textLength,
|
|
2693
|
+
advance: estimateTextAdvance(node)
|
|
2694
|
+
});
|
|
2695
|
+
ctx.defs.push({ type: "path", id: pathId, d });
|
|
2696
|
+
const textPath = {
|
|
2697
|
+
type: "textPath",
|
|
2698
|
+
href: "#" + pathId,
|
|
2699
|
+
children: (_a = node.children) != null ? _a : []
|
|
2700
|
+
};
|
|
2701
|
+
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
2702
|
+
if (fx.method !== void 0) textPath.method = fx.method;
|
|
2703
|
+
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
2704
|
+
applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
|
|
2705
|
+
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
2706
|
+
node.children = [textPath];
|
|
2707
|
+
return node;
|
|
2708
|
+
}
|
|
2709
|
+
function applyAnimatableNumber(node, attrName, raw) {
|
|
2710
|
+
if (raw === void 0 || raw === null) return;
|
|
2711
|
+
if (typeof raw === "number") {
|
|
2712
|
+
node[attrName] = String(raw);
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
if (typeof raw === "object" && raw !== null) {
|
|
2716
|
+
const obj = raw;
|
|
2717
|
+
if (Array.isArray(obj.keyframes)) {
|
|
2718
|
+
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
2719
|
+
const animate = __spreadValues({}, prevAnimate || {});
|
|
2720
|
+
const block = { keyframes: obj.keyframes };
|
|
2721
|
+
if (obj.loop !== void 0) block.loop = obj.loop;
|
|
2722
|
+
animate[attrName] = block;
|
|
2723
|
+
node.animate = animate;
|
|
2724
|
+
return;
|
|
2725
|
+
}
|
|
2726
|
+
if (typeof obj.value === "number") {
|
|
2727
|
+
node[attrName] = String(obj.value);
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
// src/effects/elementFactory.ts
|
|
2734
|
+
var jsonElementFactory = (type, props, children) => {
|
|
2735
|
+
const node = { type };
|
|
2736
|
+
for (const k in props) if (props[k] !== void 0) node[k] = props[k];
|
|
2737
|
+
const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
|
|
2738
|
+
if (arr.length) node.children = arr;
|
|
2739
|
+
return node;
|
|
2740
|
+
};
|
|
2741
|
+
|
|
2742
|
+
// src/effects/glyphPathBake.ts
|
|
2743
|
+
function fmt(v, decimals) {
|
|
2744
|
+
return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
|
|
2745
|
+
}
|
|
2746
|
+
function pack(nums, decimals) {
|
|
2747
|
+
let s = "";
|
|
2748
|
+
for (let i = 0; i < nums.length; i++) {
|
|
2749
|
+
const str2 = fmt(nums[i], decimals);
|
|
2750
|
+
if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
|
|
2751
|
+
s += str2;
|
|
2752
|
+
}
|
|
2753
|
+
return s;
|
|
2754
|
+
}
|
|
2755
|
+
function apply(m, x, y) {
|
|
2756
|
+
return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
2757
|
+
}
|
|
2758
|
+
var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
|
|
2759
|
+
function transformPathData(d, m, decimals = 2) {
|
|
2760
|
+
const tokens = [];
|
|
2761
|
+
let match;
|
|
2762
|
+
TOKEN_RE.lastIndex = 0;
|
|
2763
|
+
while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
|
|
2764
|
+
let out = "";
|
|
2765
|
+
let i = 0;
|
|
2766
|
+
const num2 = () => parseFloat(tokens[i++]);
|
|
2767
|
+
while (i < tokens.length) {
|
|
2768
|
+
const cmd = tokens[i++];
|
|
2769
|
+
if (cmd === "M" || cmd === "L") {
|
|
2770
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2771
|
+
out += cmd + pack([x, y], decimals);
|
|
2772
|
+
} else if (cmd === "C") {
|
|
2773
|
+
const [x1, y1] = apply(m, num2(), num2());
|
|
2774
|
+
const [x2, y2] = apply(m, num2(), num2());
|
|
2775
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2776
|
+
out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
|
|
2777
|
+
} else if (cmd === "Q") {
|
|
2778
|
+
const [x1, y1] = apply(m, num2(), num2());
|
|
2779
|
+
const [x, y] = apply(m, num2(), num2());
|
|
2780
|
+
out += "Q" + pack([x1, y1, x, y], decimals);
|
|
2781
|
+
} else if (cmd === "Z" || cmd === "z") {
|
|
2782
|
+
out += "Z";
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
return out;
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2688
2788
|
// src/effects/textGlyphsEffect.ts
|
|
2689
2789
|
var DEFAULT_FONT_SIZE = 16;
|
|
2690
2790
|
var TEXT_ATTR_KEYS = [
|
|
@@ -2763,6 +2863,19 @@ function soleFontOf(glyphs) {
|
|
|
2763
2863
|
const names = Object.keys(glyphs);
|
|
2764
2864
|
return names.length === 1 ? glyphs[names[0]] : void 0;
|
|
2765
2865
|
}
|
|
2866
|
+
var MISSING_GLYPH_ADVANCE_EM = 0.6;
|
|
2867
|
+
function missingGlyphBoxEm(advanceEm, ascentEm) {
|
|
2868
|
+
if (advanceEm <= 0 || ascentEm <= 0) return "";
|
|
2869
|
+
const inset = 0.08;
|
|
2870
|
+
const x0 = advanceEm * inset, x1 = advanceEm * (1 - inset);
|
|
2871
|
+
const y1 = -ascentEm * (1 - inset);
|
|
2872
|
+
const bw = x1 - x0, bh = -y1;
|
|
2873
|
+
const t = Math.max(1, Math.min(bw, bh) * 0.12);
|
|
2874
|
+
const outer = "M" + x0 + " 0L" + x1 + " 0L" + x1 + " " + y1 + "L" + x0 + " " + y1 + "Z";
|
|
2875
|
+
if (bw <= 2 * t || bh <= 2 * t) return outer;
|
|
2876
|
+
const ix0 = x0 + t, ix1 = x1 - t, iyb = -t, iyt = y1 + t;
|
|
2877
|
+
return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
|
|
2878
|
+
}
|
|
2766
2879
|
function materialiseGlyphTextHorizontal(node, opts) {
|
|
2767
2880
|
var _a, _b, _c, _d;
|
|
2768
2881
|
const { glyphs, create = jsonElementFactory, warnings } = opts;
|
|
@@ -2772,15 +2885,26 @@ function materialiseGlyphTextHorizontal(node, opts) {
|
|
|
2772
2885
|
const lines = [{ start: pen.x, end: pen.x }];
|
|
2773
2886
|
let line = 0;
|
|
2774
2887
|
const renderChars = (content, s) => {
|
|
2888
|
+
var _a2;
|
|
2775
2889
|
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2776
|
-
|
|
2777
|
-
const scale = s.fontSize /
|
|
2890
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
2891
|
+
const scale = s.fontSize / upm;
|
|
2892
|
+
const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
|
|
2778
2893
|
const paint = paintOf(s);
|
|
2779
2894
|
for (let i = 0; i < content.length; i++) {
|
|
2780
2895
|
const ch = content.charAt(i);
|
|
2781
|
-
const g = gf.glyphs[ch];
|
|
2782
|
-
if (g && g.d)
|
|
2783
|
-
|
|
2896
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
2897
|
+
if (g && g.d) {
|
|
2898
|
+
placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
|
|
2899
|
+
pen.x += g.width * scale;
|
|
2900
|
+
} else if (/\S/.test(ch)) {
|
|
2901
|
+
const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
|
|
2902
|
+
placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
|
|
2903
|
+
pen.x += advEm * scale;
|
|
2904
|
+
} else {
|
|
2905
|
+
pen.x += (g ? g.width : 0) * scale;
|
|
2906
|
+
}
|
|
2907
|
+
pen.x += s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2784
2908
|
lines[line].end = pen.x;
|
|
2785
2909
|
}
|
|
2786
2910
|
};
|
|
@@ -2815,24 +2939,152 @@ function materialiseGlyphTextHorizontal(node, opts) {
|
|
|
2815
2939
|
}
|
|
2816
2940
|
return toGroup(node, buildPaths(placements, create, warnings), create);
|
|
2817
2941
|
}
|
|
2942
|
+
function layoutGlyphTextChars(node, opts) {
|
|
2943
|
+
var _a, _b, _c, _d, _e;
|
|
2944
|
+
if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
|
|
2945
|
+
const { glyphs, warnings } = opts;
|
|
2946
|
+
const soleFont = soleFontOf(glyphs);
|
|
2947
|
+
const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
|
|
2948
|
+
const boxes = [];
|
|
2949
|
+
const lines = [{ start: pen.x, end: pen.x }];
|
|
2950
|
+
let line = 0;
|
|
2951
|
+
const renderChars = (content, s) => {
|
|
2952
|
+
var _a2;
|
|
2953
|
+
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2954
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
2955
|
+
const scale = s.fontSize / upm;
|
|
2956
|
+
const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
|
|
2957
|
+
for (let i = 0; i < content.length; i++) {
|
|
2958
|
+
const ch = content.charAt(i);
|
|
2959
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
2960
|
+
const advance = (g ? g.width : 0) * scale + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2961
|
+
boxes.push({ x: pen.x, y: pen.y, width: advance, ascent, fontSize: s.fontSize, line });
|
|
2962
|
+
pen.x += advance;
|
|
2963
|
+
lines[line].end = pen.x;
|
|
2964
|
+
}
|
|
2965
|
+
};
|
|
2966
|
+
const walk = (el, parentStyle) => {
|
|
2967
|
+
var _a2, _b2, _c2, _d2;
|
|
2968
|
+
const s = resolveStyle(el, parentStyle);
|
|
2969
|
+
const x = parseLen(el.x);
|
|
2970
|
+
const y = parseLen(el.y);
|
|
2971
|
+
if (x !== void 0) {
|
|
2972
|
+
pen.x = x;
|
|
2973
|
+
line = lines.length;
|
|
2974
|
+
lines.push({ start: pen.x, end: pen.x });
|
|
2975
|
+
}
|
|
2976
|
+
if (y !== void 0) pen.y = y;
|
|
2977
|
+
pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
|
|
2978
|
+
pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
|
|
2979
|
+
const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
|
|
2980
|
+
if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
|
|
2981
|
+
if (el.children) for (const ch of el.children) walk(ch, s);
|
|
2982
|
+
};
|
|
2983
|
+
const rootStyle = rootStyleOf(node);
|
|
2984
|
+
if (node.children) for (const ch of node.children) walk(ch, rootStyle);
|
|
2985
|
+
const rootContent = (_d = str(node[TEXT_ATTR])) != null ? _d : str(node[TEXT_CONTENT_ATTR]);
|
|
2986
|
+
if (rootContent && !((_e = node.children) == null ? void 0 : _e.length)) renderChars(rootContent, rootStyle);
|
|
2987
|
+
const anchor = str(node.textAnchor);
|
|
2988
|
+
if (anchor === "middle" || anchor === "end") {
|
|
2989
|
+
for (const b of boxes) {
|
|
2990
|
+
const w = lines[b.line].end - lines[b.line].start;
|
|
2991
|
+
b.x += anchor === "middle" ? -w / 2 : -w;
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
return boxes.map((_f) => {
|
|
2995
|
+
var _g = _f, { line: _l } = _g, b = __objRest(_g, ["line"]);
|
|
2996
|
+
return b;
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
|
|
3000
|
+
var _a;
|
|
3001
|
+
const { glyphs, warnings, alongPath } = opts;
|
|
3002
|
+
const sampler = createPathSampler(pathD);
|
|
3003
|
+
if (!sampler) {
|
|
3004
|
+
warnings == null ? void 0 : warnings.push("textGlyphs: unparsable along-path geometry (caret)");
|
|
3005
|
+
return [];
|
|
3006
|
+
}
|
|
3007
|
+
const soleFont = soleFontOf(glyphs);
|
|
3008
|
+
const chars = [];
|
|
3009
|
+
let adv = 0;
|
|
3010
|
+
const walk = (el, parentStyle) => {
|
|
3011
|
+
var _a2, _b, _c;
|
|
3012
|
+
const s = resolveStyle(el, parentStyle);
|
|
3013
|
+
const content = (_a2 = str(el[TEXT_ATTR])) != null ? _a2 : str(el[TEXT_CONTENT_ATTR]);
|
|
3014
|
+
if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
|
|
3015
|
+
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
3016
|
+
const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
|
|
3017
|
+
const scale = s.fontSize / upm;
|
|
3018
|
+
const ascent = ((_c = gf == null ? void 0 : gf.ascent) != null ? _c : 0.9 * upm) * scale;
|
|
3019
|
+
for (let i = 0; i < content.length; i++) {
|
|
3020
|
+
const ch = content.charAt(i);
|
|
3021
|
+
const g = gf == null ? void 0 : gf.glyphs[ch];
|
|
3022
|
+
const glyphW = (g ? g.width : 0) * scale;
|
|
3023
|
+
const advance = glyphW + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
3024
|
+
chars.push({ advStart: adv, advEnd: adv + advance, glyphW, ascent, fontSize: s.fontSize });
|
|
3025
|
+
adv += advance;
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
if (el.children) for (const ch of el.children) walk(ch, s);
|
|
3029
|
+
};
|
|
3030
|
+
walk(node, rootStyleOf(node));
|
|
3031
|
+
const width = adv;
|
|
3032
|
+
const k = (alongPath == null ? void 0 : alongPath.textLength) && alongPath.textLength > 0 && width > 0 ? alongPath.textLength / width : 1;
|
|
3033
|
+
const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
|
|
3034
|
+
const { along: alongOffset, perp } = alongPathNodeOffsets(node);
|
|
3035
|
+
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);
|
|
3036
|
+
const withPerp = (p) => ({
|
|
3037
|
+
x: p.x - perp * Math.sin(p.angle),
|
|
3038
|
+
y: p.y + perp * Math.cos(p.angle),
|
|
3039
|
+
angle: p.angle
|
|
3040
|
+
});
|
|
3041
|
+
return chars.map((c) => {
|
|
3042
|
+
const dStart = base + c.advStart * k;
|
|
3043
|
+
const dEnd = base + c.advEnd * k;
|
|
3044
|
+
const p0 = withPerp(sampler.sampleAtDistance(dStart));
|
|
3045
|
+
const p1 = withPerp(sampler.sampleAtDistance(dEnd));
|
|
3046
|
+
const glyphMid = sampler.sampleAtDistance(base + (c.advStart + c.glyphW / 2) * k);
|
|
3047
|
+
return {
|
|
3048
|
+
x: p0.x,
|
|
3049
|
+
y: p0.y,
|
|
3050
|
+
width: c.advEnd - c.advStart,
|
|
3051
|
+
ascent: c.ascent,
|
|
3052
|
+
fontSize: c.fontSize,
|
|
3053
|
+
endX: p1.x,
|
|
3054
|
+
endY: p1.y,
|
|
3055
|
+
rotation: glyphMid.angle * 180 / Math.PI
|
|
3056
|
+
};
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
2818
3059
|
function collectAlongPathCells(node, glyphs, soleFont, warnings) {
|
|
2819
3060
|
const cells = [];
|
|
2820
3061
|
let adv = 0;
|
|
2821
3062
|
const walk = (el, parentStyle) => {
|
|
2822
|
-
var _a, _b;
|
|
3063
|
+
var _a, _b, _c;
|
|
2823
3064
|
const s = resolveStyle(el, parentStyle);
|
|
2824
3065
|
const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
|
|
2825
3066
|
if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
|
|
2826
3067
|
const gf = glyphFontFor(s, glyphs, soleFont, warnings);
|
|
2827
3068
|
if (gf) {
|
|
2828
3069
|
const scale = s.fontSize / gf.unitsPerEm;
|
|
3070
|
+
const ascentEm = (_c = gf.ascent) != null ? _c : 0.9 * gf.unitsPerEm;
|
|
2829
3071
|
const paint = paintOf(s);
|
|
2830
3072
|
for (let i = 0; i < content.length; i++) {
|
|
2831
3073
|
const ch = content.charAt(i);
|
|
2832
3074
|
const g = gf.glyphs[ch];
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
3075
|
+
if (g && g.d) {
|
|
3076
|
+
const glyphAdv = g.width * scale;
|
|
3077
|
+
cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
|
|
3078
|
+
adv += glyphAdv;
|
|
3079
|
+
} else if (/\S/.test(ch)) {
|
|
3080
|
+
const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
|
|
3081
|
+
const boxAdv = wEm * scale;
|
|
3082
|
+
cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, midBase: adv + boxAdv / 2 });
|
|
3083
|
+
adv += boxAdv;
|
|
3084
|
+
} else {
|
|
3085
|
+
adv += (g ? g.width : 0) * scale;
|
|
3086
|
+
}
|
|
3087
|
+
adv += s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
|
|
2836
3088
|
}
|
|
2837
3089
|
}
|
|
2838
3090
|
}
|
|
@@ -2841,12 +3093,19 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
|
|
|
2841
3093
|
walk(node, rootStyleOf(node));
|
|
2842
3094
|
return { cells, width: adv };
|
|
2843
3095
|
}
|
|
2844
|
-
function alongAffine(sampler, dist, scale, widthEm) {
|
|
3096
|
+
function alongAffine(sampler, dist, scale, widthEm, perp = 0) {
|
|
2845
3097
|
const { x, y, angle } = sampler.sampleAtDistance(dist);
|
|
2846
3098
|
const cos = Math.cos(angle), sin = Math.sin(angle), hw = widthEm / 2;
|
|
2847
|
-
return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw, y - scale * sin * hw];
|
|
3099
|
+
return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
|
|
3100
|
+
}
|
|
3101
|
+
function alongPathNodeOffsets(node) {
|
|
3102
|
+
var _a, _b, _c;
|
|
3103
|
+
return {
|
|
3104
|
+
along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
|
|
3105
|
+
perp: (_c = parseLen(node.dy)) != null ? _c : 0
|
|
3106
|
+
};
|
|
2848
3107
|
}
|
|
2849
|
-
function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength) {
|
|
3108
|
+
function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
|
|
2850
3109
|
var _a;
|
|
2851
3110
|
const { glyphs, create = jsonElementFactory, warnings } = opts;
|
|
2852
3111
|
const sampler = pathD ? createPathSampler(pathD) : null;
|
|
@@ -2857,19 +3116,25 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
|
|
|
2857
3116
|
const soleFont = soleFontOf(glyphs);
|
|
2858
3117
|
const { cells, width } = collectAlongPathCells(node, glyphs, soleFont, warnings);
|
|
2859
3118
|
if (!cells.length) return toGroup(node, [], create);
|
|
3119
|
+
const { along: alongOffset, perp } = alongPathNodeOffsets(node);
|
|
2860
3120
|
if (textLength && textLength > 0 && width > 0) {
|
|
2861
3121
|
const k = textLength / width;
|
|
2862
3122
|
for (const c of cells) c.midBase *= k;
|
|
2863
3123
|
}
|
|
3124
|
+
const isClip = pathOverflow === "clip" && !sampler.closed;
|
|
2864
3125
|
const so = readAnimatable(startOffset);
|
|
2865
3126
|
if (so.kind === "animated" /* Animated */ && so.keyframes.length >= 2) {
|
|
2866
|
-
return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create), create);
|
|
2867
|
-
}
|
|
2868
|
-
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;
|
|
2869
|
-
const
|
|
3127
|
+
return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create, isClip, alongOffset, perp), create);
|
|
3128
|
+
}
|
|
3129
|
+
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);
|
|
3130
|
+
const placeCells = isClip ? cells.filter((c) => {
|
|
3131
|
+
const d = base + c.midBase;
|
|
3132
|
+
return d >= 0 && d <= sampler.totalLength;
|
|
3133
|
+
}) : cells;
|
|
3134
|
+
const placements = placeCells.map((c) => ({
|
|
2870
3135
|
glyphD: c.glyphD,
|
|
2871
3136
|
paint: c.paint,
|
|
2872
|
-
m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm)
|
|
3137
|
+
m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm, perp)
|
|
2873
3138
|
}));
|
|
2874
3139
|
return toGroup(node, buildPaths(placements, create, warnings), create);
|
|
2875
3140
|
}
|
|
@@ -2879,37 +3144,51 @@ function roundN(v, n) {
|
|
|
2879
3144
|
const f = __pow(10, n);
|
|
2880
3145
|
return Math.round(v * f) / f;
|
|
2881
3146
|
}
|
|
2882
|
-
function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create) {
|
|
3147
|
+
function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create, isClip, alongOffset = 0, perp = 0) {
|
|
2883
3148
|
const step = Math.max(sampler.totalLength / ALONG_PATH_MAX_STEPS, 0.5);
|
|
2884
3149
|
const timeOf = (kf) => Number(kf.time) || 0;
|
|
2885
|
-
const offOf = (kf) => Number(kf.value) || 0;
|
|
3150
|
+
const offOf = (kf) => alongOffset + (Number(kf.value) || 0);
|
|
3151
|
+
const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
|
|
2886
3152
|
const out = [];
|
|
2887
3153
|
for (const c of cells) {
|
|
2888
3154
|
const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
|
|
2889
3155
|
const d = transformPathData(c.glyphD, centred);
|
|
2890
3156
|
const sampleKf = (dist, time) => {
|
|
2891
3157
|
const { x, y, angle } = sampler.sampleAtDistance(dist);
|
|
3158
|
+
const cos = Math.cos(angle), sin = Math.sin(angle);
|
|
2892
3159
|
return {
|
|
2893
3160
|
time,
|
|
2894
3161
|
value: {
|
|
2895
|
-
["translate" /* Translate */]: [roundN(x, 3), roundN(y, 3)],
|
|
3162
|
+
["translate" /* Translate */]: [roundN(x - perp * sin, 3), roundN(y + perp * cos, 3)],
|
|
2896
3163
|
["rotate" /* Rotate */]: roundN(angle * 180 / Math.PI, 3)
|
|
2897
3164
|
}
|
|
2898
3165
|
};
|
|
2899
3166
|
};
|
|
2900
|
-
const kfs = [
|
|
3167
|
+
const kfs = [];
|
|
3168
|
+
const opKfs = [];
|
|
3169
|
+
const pushKf = (dist, time) => {
|
|
3170
|
+
kfs.push(sampleKf(dist, time));
|
|
3171
|
+
if (isClip) opKfs.push({ time, value: onPath(dist) ? 1 : 0 });
|
|
3172
|
+
};
|
|
3173
|
+
pushKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]));
|
|
2901
3174
|
for (let k = 1; k < sokfs.length; k++) {
|
|
2902
3175
|
const t0 = timeOf(sokfs[k - 1]), t1 = timeOf(sokfs[k]);
|
|
2903
3176
|
const o0 = offOf(sokfs[k - 1]), o1 = offOf(sokfs[k]);
|
|
2904
3177
|
const n = Math.min(ALONG_PATH_MAX_STEPS_PER_SEGMENT, Math.max(1, Math.ceil(Math.abs(o1 - o0) / step)));
|
|
2905
3178
|
for (let s = 1; s <= n; s++) {
|
|
2906
3179
|
const f = s / n;
|
|
2907
|
-
|
|
3180
|
+
pushKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0));
|
|
2908
3181
|
}
|
|
2909
3182
|
}
|
|
2910
3183
|
const transform = { keyframes: kfs };
|
|
2911
3184
|
if (loop !== void 0) transform.loop = loop;
|
|
2912
|
-
|
|
3185
|
+
const animate = { transform };
|
|
3186
|
+
if (isClip && opKfs.some((k) => k.value === 0)) {
|
|
3187
|
+
const op = { keyframes: opKfs };
|
|
3188
|
+
if (loop !== void 0) op.loop = loop;
|
|
3189
|
+
animate.opacity = op;
|
|
3190
|
+
}
|
|
3191
|
+
out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
|
|
2913
3192
|
}
|
|
2914
3193
|
return out;
|
|
2915
3194
|
}
|
|
@@ -2953,7 +3232,7 @@ function toGroup(node, children, create) {
|
|
|
2953
3232
|
return create("g", gProps, children);
|
|
2954
3233
|
}
|
|
2955
3234
|
function materialiseGlyphText(node, opts) {
|
|
2956
|
-
if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength);
|
|
3235
|
+
if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
|
|
2957
3236
|
return materialiseGlyphTextHorizontal(node, opts);
|
|
2958
3237
|
}
|
|
2959
3238
|
function applyTextGlyphsEffect(node, fx, ctx) {
|
|
@@ -2964,12 +3243,12 @@ function applyTextGlyphsEffect(node, fx, ctx) {
|
|
|
2964
3243
|
}
|
|
2965
3244
|
return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
|
|
2966
3245
|
}
|
|
2967
|
-
function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength) {
|
|
3246
|
+
function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
|
|
2968
3247
|
if (!ctx.glyphs) {
|
|
2969
3248
|
ctx.warnings.push("textGlyphs: no definitions.glyphs");
|
|
2970
3249
|
return null;
|
|
2971
3250
|
}
|
|
2972
|
-
return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength);
|
|
3251
|
+
return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
|
|
2973
3252
|
}
|
|
2974
3253
|
|
|
2975
3254
|
// src/PxMotionPath.ts
|
|
@@ -3150,9 +3429,18 @@ function buildOutKfValue(prevV, nextV, p, translate, rotateDegFromAutoOrient, au
|
|
|
3150
3429
|
if (pv === void 0 && nv === void 0) continue;
|
|
3151
3430
|
value[k] = interpolatePart(pv, nv, p);
|
|
3152
3431
|
}
|
|
3153
|
-
if (rotateDegFromAutoOrient !== void 0)
|
|
3432
|
+
if (rotateDegFromAutoOrient !== void 0) {
|
|
3433
|
+
value.rotate = rotateDegFromAutoOrient + explicitRotateAt(prevV, nextV, p);
|
|
3434
|
+
}
|
|
3154
3435
|
return value;
|
|
3155
3436
|
}
|
|
3437
|
+
function explicitRotateAt(prevV, nextV, p) {
|
|
3438
|
+
const pv = typeof (prevV == null ? void 0 : prevV.rotate) === "number" ? prevV.rotate : void 0;
|
|
3439
|
+
const nv = typeof (nextV == null ? void 0 : nextV.rotate) === "number" ? nextV.rotate : void 0;
|
|
3440
|
+
if (pv === void 0 && nv === void 0) return 0;
|
|
3441
|
+
const r = interpolatePart(pv, nv, p);
|
|
3442
|
+
return typeof r === "number" ? r : 0;
|
|
3443
|
+
}
|
|
3156
3444
|
function derivAngleForFirstKf(kf0, kf1) {
|
|
3157
3445
|
const p0 = getKfTranslate(kf0);
|
|
3158
3446
|
const p1 = getKfTranslate(kf1);
|
|
@@ -3173,10 +3461,12 @@ function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos,
|
|
|
3173
3461
|
const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
|
|
3174
3462
|
const prevExit = lastV == null ? void 0 : lastV.rotate;
|
|
3175
3463
|
if (typeof prevExit !== "number") return;
|
|
3464
|
+
const boundaryV = getKfValueParts(prevKf);
|
|
3465
|
+
const prevExitTangent = prevExit - explicitRotateAt(boundaryV, boundaryV, 0);
|
|
3176
3466
|
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
3177
3467
|
const tanAtStart = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
|
|
3178
3468
|
const nextEntry = Math.atan2(tanAtStart[1], tanAtStart[0]) * 180 / Math.PI;
|
|
3179
|
-
const delta = wrappedAngleDelta(nextEntry,
|
|
3469
|
+
const delta = wrappedAngleDelta(nextEntry, prevExitTangent);
|
|
3180
3470
|
if (Math.abs(delta) <= rotationTol) return;
|
|
3181
3471
|
const dupValue = buildOutKfValue(
|
|
3182
3472
|
getKfValueParts(prevKf),
|
|
@@ -4375,18 +4665,17 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
4375
4665
|
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
4376
4666
|
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
4377
4667
|
if (!fx && !innerIdForContentRef) return node;
|
|
4378
|
-
const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient,
|
|
4668
|
+
const { transformation, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
|
|
4379
4669
|
const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
|
|
4380
4670
|
if (fx) delete node.effects;
|
|
4381
4671
|
let n = node;
|
|
4382
4672
|
let consumedByGlyphs = false;
|
|
4383
4673
|
if (text == null ? void 0 : text.useGlyphs) {
|
|
4384
|
-
if (
|
|
4385
|
-
const
|
|
4386
|
-
const
|
|
4387
|
-
const rawTL = textAlongPath.textLength;
|
|
4674
|
+
if (textPath) {
|
|
4675
|
+
const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
|
|
4676
|
+
const rawTL = textPath.textLength;
|
|
4388
4677
|
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;
|
|
4389
|
-
const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD,
|
|
4678
|
+
const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textLength, textPath.pathOverflow);
|
|
4390
4679
|
if (glyphed) {
|
|
4391
4680
|
n = glyphed;
|
|
4392
4681
|
consumedByGlyphs = true;
|
|
@@ -4396,12 +4685,13 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
4396
4685
|
consumedByGlyphs = true;
|
|
4397
4686
|
}
|
|
4398
4687
|
}
|
|
4399
|
-
if (!consumedByGlyphs) n =
|
|
4688
|
+
if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
|
|
4400
4689
|
n = applyFillGradientEffect(n, fillGradient, ctx);
|
|
4401
4690
|
n = applyStrokeGradientEffect(n, strokeGradient, ctx);
|
|
4402
4691
|
n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
|
|
4403
4692
|
n = applyRepeaterEffect(n, repeater, ctx);
|
|
4404
4693
|
n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
|
|
4694
|
+
n = applyClipPathEffect(n, clipPath, ctx);
|
|
4405
4695
|
if (innerIdForContentRef) {
|
|
4406
4696
|
applyRefHref(n, cloneFx, ctx);
|
|
4407
4697
|
n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
|
|
@@ -4730,6 +5020,8 @@ function getNormalizedProps(props) {
|
|
|
4730
5020
|
function renderNode(node, defs) {
|
|
4731
5021
|
if (!node) return null;
|
|
4732
5022
|
const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
|
|
5023
|
+
const feFuncType = props.funcType;
|
|
5024
|
+
if (feFuncType !== void 0) delete props.funcType;
|
|
4733
5025
|
const nodeDefs = getDefs(node) || defs;
|
|
4734
5026
|
const resolvedStyle = resolveStyle2(style, nodeDefs);
|
|
4735
5027
|
let childElements;
|
|
@@ -4742,13 +5034,15 @@ function renderNode(node, defs) {
|
|
|
4742
5034
|
}
|
|
4743
5035
|
}
|
|
4744
5036
|
}
|
|
4745
|
-
|
|
5037
|
+
const element = createElement(
|
|
4746
5038
|
type || "g",
|
|
4747
5039
|
getNormalizedProps(props),
|
|
4748
5040
|
resolvedStyle,
|
|
4749
5041
|
childElements,
|
|
4750
5042
|
props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
|
|
4751
5043
|
);
|
|
5044
|
+
if (element && feFuncType !== void 0) element.setAttribute("type", feFuncType);
|
|
5045
|
+
return element;
|
|
4752
5046
|
}
|
|
4753
5047
|
|
|
4754
5048
|
// src/PxAnimatorTriggers.ts
|
|
@@ -4759,7 +5053,12 @@ function setupAnimationTriggers(api, config) {
|
|
|
4759
5053
|
console.warn("setupAnimationTriggers: No root element found for animation.");
|
|
4760
5054
|
return api;
|
|
4761
5055
|
}
|
|
5056
|
+
let reversed = false;
|
|
4762
5057
|
const start = () => {
|
|
5058
|
+
if (reversed) {
|
|
5059
|
+
reversed = false;
|
|
5060
|
+
api.setPlaybackRate(1);
|
|
5061
|
+
}
|
|
4763
5062
|
api.play();
|
|
4764
5063
|
};
|
|
4765
5064
|
const handleEndAction = () => {
|
|
@@ -4771,6 +5070,8 @@ function setupAnimationTriggers(api, config) {
|
|
|
4771
5070
|
api.cancel();
|
|
4772
5071
|
break;
|
|
4773
5072
|
case "reverse":
|
|
5073
|
+
reversed = true;
|
|
5074
|
+
api.setPlaybackRate(-1);
|
|
4774
5075
|
api.play();
|
|
4775
5076
|
break;
|
|
4776
5077
|
case "continue":
|
|
@@ -4833,6 +5134,7 @@ function getSelector(id) {
|
|
|
4833
5134
|
return "#" + id;
|
|
4834
5135
|
}
|
|
4835
5136
|
function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
5137
|
+
var _a;
|
|
4836
5138
|
const config = getAnimatorConfig(doc) || {};
|
|
4837
5139
|
const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
|
|
4838
5140
|
const _iterations = config.iterations;
|
|
@@ -4843,18 +5145,24 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4843
5145
|
const duration = +(config.duration || DEFAULT_DURATION_MS);
|
|
4844
5146
|
const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
|
|
4845
5147
|
const direction = config.direction || "normal";
|
|
5148
|
+
const fill = (_a = config.fill) != null ? _a : "forwards";
|
|
5149
|
+
const fillsForwards = fill === "forwards" || fill === "both";
|
|
5150
|
+
const fillsBackwards = fill === "backwards" || fill === "both";
|
|
4846
5151
|
let timerId = null;
|
|
4847
5152
|
let playing = false;
|
|
4848
|
-
let timeBeforeLastStartMs = config.delay || 0;
|
|
5153
|
+
let timeBeforeLastStartMs = -(config.delay || 0);
|
|
4849
5154
|
let lastStartedTs = 0;
|
|
4850
5155
|
let playbackRate = 1;
|
|
4851
5156
|
let finishCalled = false;
|
|
4852
5157
|
const frameRate = config.frameRate;
|
|
4853
5158
|
const minFrameIntervalMs = frameRate && frameRate > 0 ? 1e3 / frameRate : 0;
|
|
4854
5159
|
let lastRenderTs = 0;
|
|
4855
|
-
const
|
|
5160
|
+
const getRawAnimTime = () => {
|
|
4856
5161
|
const runningElapsed = lastStartedTs ? (Date.now() - lastStartedTs) * playbackRate : 0;
|
|
4857
|
-
|
|
5162
|
+
return timeBeforeLastStartMs + runningElapsed;
|
|
5163
|
+
};
|
|
5164
|
+
const getAnimCurrentTime = () => {
|
|
5165
|
+
let time = getRawAnimTime();
|
|
4858
5166
|
if (Number.isFinite(totalDuration) && time > totalDuration) time = totalDuration;
|
|
4859
5167
|
if (time < 0) time = 0;
|
|
4860
5168
|
return time;
|
|
@@ -4899,40 +5207,59 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4899
5207
|
}
|
|
4900
5208
|
}
|
|
4901
5209
|
const tick = () => {
|
|
4902
|
-
var
|
|
5210
|
+
var _a2, _b;
|
|
4903
5211
|
if (!adapter.isConnected()) {
|
|
4904
5212
|
pauseAnim();
|
|
4905
5213
|
return;
|
|
4906
5214
|
}
|
|
4907
5215
|
const currentTime = getAnimCurrentTime();
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
if (
|
|
4911
|
-
|
|
4912
|
-
}
|
|
4913
|
-
lastRenderTs = now;
|
|
4914
|
-
}
|
|
4915
|
-
if (duration <= 0) {
|
|
5216
|
+
const rawTime = getRawAnimTime();
|
|
5217
|
+
if (rawTime < 0 && playbackRate > 0) {
|
|
5218
|
+
if (fillsBackwards) renderFrame(0);
|
|
5219
|
+
return;
|
|
4916
5220
|
}
|
|
4917
|
-
if (
|
|
4918
|
-
|
|
5221
|
+
if (playbackRate < 0 && rawTime <= 0) {
|
|
5222
|
+
pauseAnim();
|
|
5223
|
+
renderFrame(0);
|
|
4919
5224
|
if (!finishCalled) {
|
|
4920
5225
|
finishCalled = true;
|
|
4921
|
-
(
|
|
5226
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
4922
5227
|
}
|
|
5228
|
+
return;
|
|
5229
|
+
}
|
|
5230
|
+
if (playbackRate > 0 && totalDuration && Number.isFinite(totalDuration) && currentTime >= totalDuration) {
|
|
4923
5231
|
pauseAnim();
|
|
5232
|
+
renderFrame(fillsForwards ? totalDuration : 0);
|
|
5233
|
+
if (!finishCalled) {
|
|
5234
|
+
finishCalled = true;
|
|
5235
|
+
(_b = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _b.call(callbacks);
|
|
5236
|
+
}
|
|
4924
5237
|
return;
|
|
4925
5238
|
}
|
|
5239
|
+
if (minFrameIntervalMs > 0) {
|
|
5240
|
+
const now = Date.now();
|
|
5241
|
+
if (lastRenderTs && now - lastRenderTs < minFrameIntervalMs) {
|
|
5242
|
+
return;
|
|
5243
|
+
}
|
|
5244
|
+
lastRenderTs = now;
|
|
5245
|
+
}
|
|
4926
5246
|
renderFrame(currentTime);
|
|
4927
5247
|
};
|
|
4928
5248
|
if (config.delay) {
|
|
4929
|
-
|
|
5249
|
+
if (config.delay < 0) {
|
|
5250
|
+
renderFrame(getAnimCurrentTime());
|
|
5251
|
+
} else if (fillsBackwards) {
|
|
5252
|
+
renderFrame(0);
|
|
5253
|
+
}
|
|
4930
5254
|
}
|
|
4931
5255
|
const _isPlaying = () => {
|
|
4932
5256
|
if (!playing) return false;
|
|
4933
5257
|
if (!adapter.isConnected()) {
|
|
4934
5258
|
return false;
|
|
4935
5259
|
}
|
|
5260
|
+
if (playbackRate < 0) {
|
|
5261
|
+
return getRawAnimTime() > 0;
|
|
5262
|
+
}
|
|
4936
5263
|
if (Number.isFinite(totalDuration) && getAnimCurrentTime() >= totalDuration) return false;
|
|
4937
5264
|
return true;
|
|
4938
5265
|
};
|
|
@@ -4952,37 +5279,53 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4952
5279
|
};
|
|
4953
5280
|
const startAnim = () => {
|
|
4954
5281
|
if (playing) return;
|
|
4955
|
-
if (
|
|
4956
|
-
timeBeforeLastStartMs
|
|
4957
|
-
|
|
5282
|
+
if (playbackRate >= 0) {
|
|
5283
|
+
if (Number.isFinite(totalDuration) && timeBeforeLastStartMs >= totalDuration) {
|
|
5284
|
+
timeBeforeLastStartMs = 0;
|
|
5285
|
+
}
|
|
5286
|
+
} else {
|
|
5287
|
+
if (timeBeforeLastStartMs <= 0) {
|
|
5288
|
+
if (!Number.isFinite(totalDuration)) {
|
|
5289
|
+
console.warn("play: cannot start reverse playback of an infinite animation from time 0");
|
|
5290
|
+
return;
|
|
5291
|
+
}
|
|
5292
|
+
timeBeforeLastStartMs = totalDuration;
|
|
5293
|
+
}
|
|
4958
5294
|
}
|
|
5295
|
+
finishCalled = false;
|
|
4959
5296
|
playing = true;
|
|
4960
5297
|
lastStartedTs = Date.now();
|
|
4961
5298
|
loopAnim(true);
|
|
4962
5299
|
};
|
|
4963
5300
|
const pauseAnim = () => {
|
|
4964
5301
|
if (!playing) return;
|
|
4965
|
-
|
|
5302
|
+
let raw = getRawAnimTime();
|
|
5303
|
+
if (Number.isFinite(totalDuration) && raw > totalDuration) raw = totalDuration;
|
|
5304
|
+
timeBeforeLastStartMs = raw;
|
|
4966
5305
|
lastStartedTs = 0;
|
|
4967
5306
|
playing = false;
|
|
4968
5307
|
if (timerId !== null) {
|
|
4969
5308
|
cancelAnimationFrame(timerId);
|
|
4970
5309
|
timerId = null;
|
|
4971
5310
|
}
|
|
4972
|
-
|
|
5311
|
+
if (raw >= 0) {
|
|
5312
|
+
renderFrame(raw);
|
|
5313
|
+
} else if (fillsBackwards) {
|
|
5314
|
+
renderFrame(0);
|
|
5315
|
+
}
|
|
4973
5316
|
};
|
|
4974
5317
|
const cancelAnim = () => {
|
|
4975
|
-
var
|
|
5318
|
+
var _a2;
|
|
4976
5319
|
pauseAnim();
|
|
4977
5320
|
timeBeforeLastStartMs = 0;
|
|
4978
5321
|
lastStartedTs = 0;
|
|
4979
5322
|
playing = false;
|
|
4980
5323
|
finishCalled = false;
|
|
4981
5324
|
renderFrame(timeBeforeLastStartMs);
|
|
4982
|
-
(
|
|
5325
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
4983
5326
|
};
|
|
4984
5327
|
const finishAnim = (callOnFinish = true) => {
|
|
4985
|
-
var
|
|
5328
|
+
var _a2;
|
|
4986
5329
|
if (Number.isFinite(totalDuration)) {
|
|
4987
5330
|
timeBeforeLastStartMs = totalDuration;
|
|
4988
5331
|
} else {
|
|
@@ -4990,10 +5333,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
4990
5333
|
}
|
|
4991
5334
|
lastStartedTs = 0;
|
|
4992
5335
|
playing = false;
|
|
4993
|
-
|
|
5336
|
+
if (timerId !== null) {
|
|
5337
|
+
cancelAnimationFrame(timerId);
|
|
5338
|
+
timerId = null;
|
|
5339
|
+
}
|
|
5340
|
+
renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
|
|
4994
5341
|
if (callOnFinish && !finishCalled) {
|
|
4995
5342
|
finishCalled = true;
|
|
4996
|
-
(
|
|
5343
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
4997
5344
|
}
|
|
4998
5345
|
};
|
|
4999
5346
|
const api = {
|
|
@@ -5003,14 +5350,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
5003
5350
|
return _isPlaying();
|
|
5004
5351
|
},
|
|
5005
5352
|
"play": () => {
|
|
5006
|
-
var
|
|
5353
|
+
var _a2;
|
|
5007
5354
|
startAnim();
|
|
5008
|
-
(
|
|
5355
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
5009
5356
|
},
|
|
5010
5357
|
"pause": () => {
|
|
5011
|
-
var
|
|
5358
|
+
var _a2;
|
|
5012
5359
|
pauseAnim();
|
|
5013
|
-
(
|
|
5360
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
|
|
5014
5361
|
},
|
|
5015
5362
|
"cancel": () => {
|
|
5016
5363
|
cancelAnim();
|
|
@@ -5023,7 +5370,9 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
5023
5370
|
console.warn("setPlaybackRate: rate must be finite and non-zero");
|
|
5024
5371
|
return;
|
|
5025
5372
|
}
|
|
5026
|
-
|
|
5373
|
+
let current = getRawAnimTime();
|
|
5374
|
+
if (Number.isFinite(totalDuration) && current > totalDuration) current = totalDuration;
|
|
5375
|
+
if (rate < 0 !== playbackRate < 0) finishCalled = false;
|
|
5027
5376
|
playbackRate = rate;
|
|
5028
5377
|
timeBeforeLastStartMs = current;
|
|
5029
5378
|
if (playing) lastStartedTs = Date.now();
|
|
@@ -5036,10 +5385,13 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
5036
5385
|
if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
|
|
5037
5386
|
timeBeforeLastStartMs = newTime;
|
|
5038
5387
|
if (playing) lastStartedTs = Date.now();
|
|
5388
|
+
if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
|
|
5039
5389
|
renderFrame(getAnimCurrentTime());
|
|
5040
5390
|
},
|
|
5041
5391
|
"destroy": () => {
|
|
5392
|
+
var _a2;
|
|
5042
5393
|
api.cancel();
|
|
5394
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
5043
5395
|
}
|
|
5044
5396
|
};
|
|
5045
5397
|
return api;
|
|
@@ -5204,6 +5556,8 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5204
5556
|
if (typeof _iterations === "number") iterations = _iterations;
|
|
5205
5557
|
if (_iterations === "infinite") iterations = Infinity;
|
|
5206
5558
|
const unsupportedSet = /* @__PURE__ */ new Set();
|
|
5559
|
+
let finishNotified = false;
|
|
5560
|
+
let removeCalled = false;
|
|
5207
5561
|
if (!(bindings == null ? void 0 : bindings.length)) {
|
|
5208
5562
|
console.warn("createWebApiAnimator: No animation bindings defined");
|
|
5209
5563
|
}
|
|
@@ -5220,7 +5574,11 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5220
5574
|
}
|
|
5221
5575
|
const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
|
|
5222
5576
|
const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
|
|
5223
|
-
|
|
5577
|
+
let seekPosition;
|
|
5578
|
+
if (config.delay && config.delay < 0 && config.duration) {
|
|
5579
|
+
const rawSeek = -config.delay;
|
|
5580
|
+
seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : 1));
|
|
5581
|
+
}
|
|
5224
5582
|
const effectOptions = {
|
|
5225
5583
|
duration: config.duration,
|
|
5226
5584
|
delay: positiveDelay,
|
|
@@ -5241,13 +5599,17 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5241
5599
|
const anim = new Animation(effect, document.timeline);
|
|
5242
5600
|
if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
|
|
5243
5601
|
var _a2;
|
|
5244
|
-
|
|
5602
|
+
if (finishNotified) return;
|
|
5603
|
+
finishNotified = true;
|
|
5604
|
+
(_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
5245
5605
|
};
|
|
5246
5606
|
if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
|
|
5247
5607
|
var _a2;
|
|
5248
|
-
|
|
5608
|
+
if (removeCalled) return;
|
|
5609
|
+
removeCalled = true;
|
|
5610
|
+
(_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
5249
5611
|
};
|
|
5250
|
-
if (seekPosition) {
|
|
5612
|
+
if (seekPosition !== void 0) {
|
|
5251
5613
|
anim.currentTime = seekPosition;
|
|
5252
5614
|
}
|
|
5253
5615
|
animations.push(anim);
|
|
@@ -5271,6 +5633,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5271
5633
|
},
|
|
5272
5634
|
"play": () => {
|
|
5273
5635
|
var _a2;
|
|
5636
|
+
finishNotified = false;
|
|
5274
5637
|
animations.forEach((a) => a.play());
|
|
5275
5638
|
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
5276
5639
|
},
|
|
@@ -5281,6 +5644,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5281
5644
|
},
|
|
5282
5645
|
"cancel": () => {
|
|
5283
5646
|
var _a2;
|
|
5647
|
+
finishNotified = false;
|
|
5284
5648
|
animations.forEach((a) => a.cancel());
|
|
5285
5649
|
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
5286
5650
|
},
|
|
@@ -5310,13 +5674,19 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
5310
5674
|
return res !== null ? +res : null;
|
|
5311
5675
|
},
|
|
5312
5676
|
"setCurrentTime": (time) => {
|
|
5677
|
+
finishNotified = false;
|
|
5313
5678
|
animations.forEach((a) => {
|
|
5314
5679
|
a.currentTime = time;
|
|
5315
5680
|
});
|
|
5316
5681
|
},
|
|
5317
5682
|
"destroy": () => {
|
|
5683
|
+
var _a2;
|
|
5318
5684
|
api.cancel();
|
|
5319
5685
|
animations.splice(0, animations.length);
|
|
5686
|
+
if (!removeCalled) {
|
|
5687
|
+
removeCalled = true;
|
|
5688
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
5689
|
+
}
|
|
5320
5690
|
}
|
|
5321
5691
|
};
|
|
5322
5692
|
if (config.trigger) {
|
|
@@ -5460,7 +5830,6 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
|
5460
5830
|
const effectsWarnings = validateNodeEffects(doc);
|
|
5461
5831
|
for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
|
|
5462
5832
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
5463
|
-
animatorConfig.debug = true;
|
|
5464
5833
|
const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
|
|
5465
5834
|
doc = materialiseAllInTree(doc, engine);
|
|
5466
5835
|
let rootElement = null;
|
|
@@ -5489,37 +5858,55 @@ function createAnimator(options) {
|
|
|
5489
5858
|
return createAnimatorImpl(data, adapter, callbacks, container);
|
|
5490
5859
|
}
|
|
5491
5860
|
let animator = null;
|
|
5861
|
+
let pending = [];
|
|
5862
|
+
let destroyed = false;
|
|
5863
|
+
const enqueue = (call) => {
|
|
5864
|
+
if (animator) {
|
|
5865
|
+
call(animator);
|
|
5866
|
+
} else if (pending) {
|
|
5867
|
+
pending.push(call);
|
|
5868
|
+
}
|
|
5869
|
+
};
|
|
5492
5870
|
fetch(src).then((res) => res.json()).then((json) => {
|
|
5871
|
+
if (destroyed) return;
|
|
5493
5872
|
if (isPxElementFileFormat(json)) {
|
|
5494
5873
|
animator = createAnimatorImpl(json, adapter, callbacks, container);
|
|
5874
|
+
const queued = pending;
|
|
5875
|
+
pending = null;
|
|
5876
|
+
queued == null ? void 0 : queued.forEach((call) => call(animator));
|
|
5495
5877
|
} else {
|
|
5496
|
-
console.error(
|
|
5878
|
+
console.error('createAnimator: invalid animation document format at "' + src + '"');
|
|
5497
5879
|
}
|
|
5880
|
+
}).catch((err) => {
|
|
5881
|
+
pending = null;
|
|
5882
|
+
console.error('createAnimator: failed to load "' + src + '"', err);
|
|
5498
5883
|
});
|
|
5499
5884
|
return {
|
|
5500
5885
|
"isReady": () => !!animator,
|
|
5501
5886
|
"getRootElement": () => animator ? animator.getRootElement() : null,
|
|
5502
5887
|
"isPlaying": () => (animator == null ? void 0 : animator.isPlaying()) || false,
|
|
5503
5888
|
"play": () => {
|
|
5504
|
-
|
|
5889
|
+
enqueue((api) => api.play());
|
|
5505
5890
|
},
|
|
5506
5891
|
"pause": () => {
|
|
5507
|
-
|
|
5892
|
+
enqueue((api) => api.pause());
|
|
5508
5893
|
},
|
|
5509
5894
|
"cancel": () => {
|
|
5510
|
-
|
|
5895
|
+
enqueue((api) => api.cancel());
|
|
5511
5896
|
},
|
|
5512
5897
|
"finish": () => {
|
|
5513
|
-
|
|
5898
|
+
enqueue((api) => api.finish());
|
|
5514
5899
|
},
|
|
5515
5900
|
"setPlaybackRate": (rate) => {
|
|
5516
|
-
|
|
5901
|
+
enqueue((api) => api.setPlaybackRate(rate));
|
|
5517
5902
|
},
|
|
5518
|
-
"getCurrentTime": () =>
|
|
5903
|
+
"getCurrentTime": () => animator ? animator.getCurrentTime() : null,
|
|
5519
5904
|
"setCurrentTime": (time) => {
|
|
5520
|
-
|
|
5905
|
+
enqueue((api) => api.setCurrentTime(time));
|
|
5521
5906
|
},
|
|
5522
5907
|
"destroy": () => {
|
|
5908
|
+
destroyed = true;
|
|
5909
|
+
pending = null;
|
|
5523
5910
|
animator == null ? void 0 : animator.destroy();
|
|
5524
5911
|
}
|
|
5525
5912
|
};
|
|
@@ -5784,8 +6171,8 @@ function subtractMultiset(a, b) {
|
|
|
5784
6171
|
PxRetimeEffectSchema,
|
|
5785
6172
|
PxStrokeGradientEffectSchema,
|
|
5786
6173
|
PxSvgNodeExtra,
|
|
5787
|
-
PxTextAlongPathEffectSchema,
|
|
5788
6174
|
PxTextEffectSchema,
|
|
6175
|
+
PxTextPathEffectSchema,
|
|
5789
6176
|
PxTransformPartsSchema,
|
|
5790
6177
|
PxTransformValueSchema,
|
|
5791
6178
|
PxTransformationEffectSchema,
|
|
@@ -5801,10 +6188,12 @@ function subtractMultiset(a, b) {
|
|
|
5801
6188
|
createAnimatorImpl,
|
|
5802
6189
|
createBasicFrameLoopAnimator,
|
|
5803
6190
|
createFrameLoopAnimator,
|
|
6191
|
+
createPathSampler,
|
|
5804
6192
|
createWebApiAnimator,
|
|
5805
6193
|
describeSchema,
|
|
5806
6194
|
diffInEffect,
|
|
5807
6195
|
evaluateMotionPathSegment,
|
|
6196
|
+
extendedPathForBrowser,
|
|
5808
6197
|
generateNewIds,
|
|
5809
6198
|
getAnimatorConfig,
|
|
5810
6199
|
getBindings,
|
|
@@ -5814,6 +6203,7 @@ function subtractMultiset(a, b) {
|
|
|
5814
6203
|
isPxElementFileFormat,
|
|
5815
6204
|
isPxElementFileFormatDeep,
|
|
5816
6205
|
jsonElementFactory,
|
|
6206
|
+
layoutGlyphTextChars,
|
|
5817
6207
|
loadTagAnimators,
|
|
5818
6208
|
materialiseAllInTree,
|
|
5819
6209
|
materialiseAnimatedUseInstances,
|
|
@@ -5830,6 +6220,7 @@ function subtractMultiset(a, b) {
|
|
|
5830
6220
|
renderNode,
|
|
5831
6221
|
schemaKeys,
|
|
5832
6222
|
setupAnimationTriggers,
|
|
6223
|
+
shiftAnimatable,
|
|
5833
6224
|
toRGBA,
|
|
5834
6225
|
validateNodeEffects,
|
|
5835
6226
|
visualModelAt
|