reframe-video 0.1.1 → 0.1.2
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/dist/analyze.js +44 -1
- package/dist/bin.js +262 -7
- package/dist/browserEntry.js +259 -3
- package/dist/cli.js +222 -5
- package/dist/index.js +510 -16
- package/dist/renderer-canvas.js +36 -0
- package/dist/trace-cli.js +677 -0
- package/dist/types/compile.d.ts +15 -1
- package/dist/types/compose.d.ts +12 -2
- package/dist/types/dsl.d.ts +27 -1
- package/dist/types/evaluate.d.ts +9 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/ir.d.ts +67 -1
- package/dist/types/motion.d.ts +54 -0
- package/dist/types/path.d.ts +15 -0
- package/dist/types/presets.d.ts +41 -0
- package/guides/edsl-guide.md +19 -0
- package/package.json +1 -1
- package/preview/src/main.ts +62 -0
- package/preview/src/panel.ts +37 -3
- package/preview/src/store.ts +28 -2
package/dist/browserEntry.js
CHANGED
|
@@ -3,9 +3,88 @@
|
|
|
3
3
|
// ../core/src/ir.ts
|
|
4
4
|
var DEFAULT_TO_DURATION = 0.5;
|
|
5
5
|
var DEFAULT_TWEEN_DURATION = 0.5;
|
|
6
|
+
var DEFAULT_MOTIONPATH_DURATION = 1;
|
|
7
|
+
|
|
8
|
+
// ../core/src/path.ts
|
|
9
|
+
function locate(segCount, u) {
|
|
10
|
+
if (segCount <= 0) return { i: 0, t: 0 };
|
|
11
|
+
const clamped = Math.max(0, Math.min(1, u));
|
|
12
|
+
const scaled = clamped * segCount;
|
|
13
|
+
let i = Math.floor(scaled);
|
|
14
|
+
if (i >= segCount) i = segCount - 1;
|
|
15
|
+
return { i, t: scaled - i };
|
|
16
|
+
}
|
|
17
|
+
function controls(points, closed, i) {
|
|
18
|
+
const n = points.length;
|
|
19
|
+
const at = (k) => {
|
|
20
|
+
if (closed) return points[(k % n + n) % n];
|
|
21
|
+
return points[Math.max(0, Math.min(n - 1, k))];
|
|
22
|
+
};
|
|
23
|
+
return [at(i - 1), at(i), at(i + 1), at(i + 2)];
|
|
24
|
+
}
|
|
25
|
+
function segCountOf(points, closed) {
|
|
26
|
+
const n = points.length;
|
|
27
|
+
if (n < 2) return 0;
|
|
28
|
+
return closed ? n : n - 1;
|
|
29
|
+
}
|
|
30
|
+
function pathPoint(points, closed, u) {
|
|
31
|
+
const n = points.length;
|
|
32
|
+
if (n === 0) return [0, 0];
|
|
33
|
+
if (n === 1) return [points[0][0], points[0][1]];
|
|
34
|
+
const segs = segCountOf(points, closed);
|
|
35
|
+
const { i, t } = locate(segs, u);
|
|
36
|
+
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
37
|
+
const t2 = t * t;
|
|
38
|
+
const t3 = t2 * t;
|
|
39
|
+
const f = (a, b, c, d) => 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t2 + (-a + 3 * b - 3 * c + d) * t3);
|
|
40
|
+
return [f(p0[0], p1[0], p2[0], p3[0]), f(p0[1], p1[1], p2[1], p3[1])];
|
|
41
|
+
}
|
|
42
|
+
function pathTangentAngle(points, closed, u) {
|
|
43
|
+
const n = points.length;
|
|
44
|
+
if (n < 2) return 0;
|
|
45
|
+
const segs = segCountOf(points, closed);
|
|
46
|
+
const { i, t } = locate(segs, u);
|
|
47
|
+
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
48
|
+
const t2 = t * t;
|
|
49
|
+
const d = (a, b, c, e) => 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - e) * t + 3 * (-a + 3 * b - 3 * c + e) * t2);
|
|
50
|
+
const dx = d(p0[0], p1[0], p2[0], p3[0]);
|
|
51
|
+
const dy = d(p0[1], p1[1], p2[1], p3[1]);
|
|
52
|
+
if (dx === 0 && dy === 0) return 0;
|
|
53
|
+
return Math.atan2(dy, dx) * 180 / Math.PI;
|
|
54
|
+
}
|
|
6
55
|
|
|
7
56
|
// ../core/src/compile.ts
|
|
8
57
|
var key = (target, prop) => `${target}.${prop}`;
|
|
58
|
+
function scaleTimeline(tl, k) {
|
|
59
|
+
switch (tl.kind) {
|
|
60
|
+
case "seq":
|
|
61
|
+
case "par":
|
|
62
|
+
return { ...tl, children: tl.children.map((c) => scaleTimeline(c, k)) };
|
|
63
|
+
case "stagger":
|
|
64
|
+
return { ...tl, interval: tl.interval * k, children: tl.children.map((c) => scaleTimeline(c, k)) };
|
|
65
|
+
case "wait":
|
|
66
|
+
return { ...tl, duration: tl.duration * k };
|
|
67
|
+
case "tween":
|
|
68
|
+
return { ...tl, duration: (tl.duration ?? DEFAULT_TWEEN_DURATION) * k };
|
|
69
|
+
case "motionPath":
|
|
70
|
+
return { ...tl, duration: (tl.duration ?? DEFAULT_MOTIONPATH_DURATION) * k };
|
|
71
|
+
case "to":
|
|
72
|
+
return {
|
|
73
|
+
...tl,
|
|
74
|
+
duration: (tl.duration ?? DEFAULT_TO_DURATION) * k,
|
|
75
|
+
...tl.stagger !== void 0 && { stagger: tl.stagger * k }
|
|
76
|
+
};
|
|
77
|
+
case "beat":
|
|
78
|
+
return {
|
|
79
|
+
...tl,
|
|
80
|
+
children: tl.children.map((c) => scaleTimeline(c, k)),
|
|
81
|
+
...tl.gap !== void 0 && { gap: tl.gap * k }
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function orderBeats(children) {
|
|
86
|
+
return children.map((c, i) => ({ c, i, key: c.kind === "beat" && c.order !== void 0 ? c.order : i })).sort((a, b) => a.key - b.key || a.i - b.i).map((x) => x.c);
|
|
87
|
+
}
|
|
9
88
|
function compileScene(ir) {
|
|
10
89
|
const nodeById = /* @__PURE__ */ new Map();
|
|
11
90
|
const nodeOrder = [];
|
|
@@ -34,6 +113,7 @@
|
|
|
34
113
|
}
|
|
35
114
|
}
|
|
36
115
|
const segments = /* @__PURE__ */ new Map();
|
|
116
|
+
const motionPaths = /* @__PURE__ */ new Map();
|
|
37
117
|
const current = new Map(initialValues);
|
|
38
118
|
const pushSegment = (seg) => {
|
|
39
119
|
const k = key(seg.target, seg.prop);
|
|
@@ -50,6 +130,50 @@
|
|
|
50
130
|
throw new Error(`cannot animate "${prop}" of "${target}": no base value to start from`);
|
|
51
131
|
};
|
|
52
132
|
const labelTimes = /* @__PURE__ */ new Map();
|
|
133
|
+
const beatTimes = /* @__PURE__ */ new Map();
|
|
134
|
+
const durationOf = (tl, start) => {
|
|
135
|
+
switch (tl.kind) {
|
|
136
|
+
case "seq": {
|
|
137
|
+
let t = start;
|
|
138
|
+
for (const child of orderBeats(tl.children)) t = durationOf(child, t);
|
|
139
|
+
return t;
|
|
140
|
+
}
|
|
141
|
+
case "par": {
|
|
142
|
+
let end = start;
|
|
143
|
+
for (const child of tl.children) end = Math.max(end, durationOf(child, start));
|
|
144
|
+
return end;
|
|
145
|
+
}
|
|
146
|
+
case "stagger": {
|
|
147
|
+
let end = start;
|
|
148
|
+
tl.children.forEach((child, i) => {
|
|
149
|
+
end = Math.max(end, durationOf(child, start + i * tl.interval));
|
|
150
|
+
});
|
|
151
|
+
return end;
|
|
152
|
+
}
|
|
153
|
+
case "wait":
|
|
154
|
+
return start + tl.duration;
|
|
155
|
+
case "tween":
|
|
156
|
+
return start + (tl.duration ?? DEFAULT_TWEEN_DURATION);
|
|
157
|
+
case "motionPath":
|
|
158
|
+
return start + (tl.duration ?? DEFAULT_MOTIONPATH_DURATION);
|
|
159
|
+
case "to": {
|
|
160
|
+
const override = ir.states?.[tl.state] ?? {};
|
|
161
|
+
const duration = tl.duration ?? DEFAULT_TO_DURATION;
|
|
162
|
+
const si = tl.stagger ?? 0;
|
|
163
|
+
const targets = nodeOrder.filter(
|
|
164
|
+
(id) => id in override && (tl.filter === void 0 || tl.filter.includes(id))
|
|
165
|
+
);
|
|
166
|
+
return start + duration + Math.max(0, targets.length - 1) * si;
|
|
167
|
+
}
|
|
168
|
+
case "beat": {
|
|
169
|
+
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
170
|
+
const natural = durationOf(grouping, 0);
|
|
171
|
+
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, natural) : 1);
|
|
172
|
+
const beatStart = tl.at ?? start + (tl.gap ?? 0);
|
|
173
|
+
return beatStart + k * natural;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
53
177
|
const walk = (tl, start) => {
|
|
54
178
|
const end = walkInner(tl, start);
|
|
55
179
|
if ("label" in tl && tl.label !== void 0) labelTimes.set(tl.label, { t0: start, t1: end });
|
|
@@ -59,9 +183,19 @@
|
|
|
59
183
|
switch (tl.kind) {
|
|
60
184
|
case "seq": {
|
|
61
185
|
let t = start;
|
|
62
|
-
for (const child of tl.children) t = walk(child, t);
|
|
186
|
+
for (const child of orderBeats(tl.children)) t = walk(child, t);
|
|
63
187
|
return t;
|
|
64
188
|
}
|
|
189
|
+
case "beat": {
|
|
190
|
+
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
191
|
+
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
|
|
192
|
+
const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
|
|
193
|
+
const beatStart = tl.at ?? start + (tl.gap ?? 0);
|
|
194
|
+
const end = walk(inner, beatStart);
|
|
195
|
+
beatTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
196
|
+
labelTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
197
|
+
return end;
|
|
198
|
+
}
|
|
65
199
|
case "par": {
|
|
66
200
|
let end = start;
|
|
67
201
|
for (const child of tl.children) end = Math.max(end, walk(child, start));
|
|
@@ -91,6 +225,23 @@
|
|
|
91
225
|
}
|
|
92
226
|
return start + duration;
|
|
93
227
|
}
|
|
228
|
+
case "motionPath": {
|
|
229
|
+
const duration = tl.duration ?? DEFAULT_MOTIONPATH_DURATION;
|
|
230
|
+
const points = tl.points;
|
|
231
|
+
const closed = tl.closed ?? false;
|
|
232
|
+
const autoRotate = tl.autoRotate ?? false;
|
|
233
|
+
const rotateOffset = tl.rotateOffset ?? 0;
|
|
234
|
+
let list = motionPaths.get(tl.target);
|
|
235
|
+
if (!list) motionPaths.set(tl.target, list = []);
|
|
236
|
+
list.push({ t0: start, t1: start + duration, points, closed, autoRotate, rotateOffset, ...tl.ease !== void 0 && { ease: tl.ease } });
|
|
237
|
+
if (points.length > 0) {
|
|
238
|
+
const [ex, ey] = pathPoint(points, closed, 1);
|
|
239
|
+
current.set(key(tl.target, "x"), ex);
|
|
240
|
+
current.set(key(tl.target, "y"), ey);
|
|
241
|
+
if (autoRotate) current.set(key(tl.target, "rotation"), pathTangentAngle(points, closed, 1) + rotateOffset);
|
|
242
|
+
}
|
|
243
|
+
return start + duration;
|
|
244
|
+
}
|
|
94
245
|
case "to": {
|
|
95
246
|
const override = ir.states?.[tl.state] ?? {};
|
|
96
247
|
const duration = tl.duration ?? DEFAULT_TO_DURATION;
|
|
@@ -119,14 +270,17 @@
|
|
|
119
270
|
};
|
|
120
271
|
const inferredEnd = ir.timeline ? walk(ir.timeline, 0) : 0;
|
|
121
272
|
for (const list of segments.values()) list.sort((a, b) => a.t0 - b.t0);
|
|
273
|
+
for (const list of motionPaths.values()) list.sort((a, b) => a.t0 - b.t0);
|
|
122
274
|
return {
|
|
123
275
|
ir,
|
|
124
276
|
duration: ir.duration ?? inferredEnd,
|
|
125
277
|
segments,
|
|
278
|
+
motionPaths,
|
|
126
279
|
initialValues,
|
|
127
280
|
nodeById,
|
|
128
281
|
nodeOrder,
|
|
129
|
-
labelTimes
|
|
282
|
+
labelTimes,
|
|
283
|
+
beatTimes
|
|
130
284
|
};
|
|
131
285
|
}
|
|
132
286
|
|
|
@@ -138,9 +292,13 @@
|
|
|
138
292
|
line: ["x1", "y1", "x2", "y2", "stroke", "strokeWidth", "opacity", "progress"],
|
|
139
293
|
text: [...COMMON_PROPS, "content", "contentDecimals", "fontFamily", "fontSize", "fontWeight", "fill", "letterSpacing"],
|
|
140
294
|
image: [...COMMON_PROPS, "src", "width", "height"],
|
|
295
|
+
path: [...COMMON_PROPS, "d", "fill", "stroke", "strokeWidth", "progress", "originX", "originY"],
|
|
141
296
|
group: COMMON_PROPS
|
|
142
297
|
};
|
|
143
298
|
|
|
299
|
+
// ../core/src/presets.ts
|
|
300
|
+
var SET = 1 / 120;
|
|
301
|
+
|
|
144
302
|
// ../core/src/behaviors.ts
|
|
145
303
|
function sampleBehavior(b, t) {
|
|
146
304
|
switch (b.name) {
|
|
@@ -171,6 +329,19 @@
|
|
|
171
329
|
}
|
|
172
330
|
|
|
173
331
|
// ../core/src/interpolate.ts
|
|
332
|
+
var BACK_C1 = 1.70158;
|
|
333
|
+
var BACK_C2 = BACK_C1 * 1.525;
|
|
334
|
+
var BACK_C3 = BACK_C1 + 1;
|
|
335
|
+
var ELASTIC_C4 = 2 * Math.PI / 3;
|
|
336
|
+
var ELASTIC_C5 = 2 * Math.PI / 4.5;
|
|
337
|
+
function easeOutBounce(u) {
|
|
338
|
+
const n1 = 7.5625;
|
|
339
|
+
const d1 = 2.75;
|
|
340
|
+
if (u < 1 / d1) return n1 * u * u;
|
|
341
|
+
if (u < 2 / d1) return n1 * (u -= 1.5 / d1) * u + 0.75;
|
|
342
|
+
if (u < 2.5 / d1) return n1 * (u -= 2.25 / d1) * u + 0.9375;
|
|
343
|
+
return n1 * (u -= 2.625 / d1) * u + 0.984375;
|
|
344
|
+
}
|
|
174
345
|
var EASE_TABLE = {
|
|
175
346
|
linear: (u) => u,
|
|
176
347
|
easeInQuad: (u) => u * u,
|
|
@@ -184,7 +355,20 @@
|
|
|
184
355
|
easeInOutQuart: (u) => u < 0.5 ? 8 * u ** 4 : 1 - (-2 * u + 2) ** 4 / 2,
|
|
185
356
|
easeInExpo: (u) => u === 0 ? 0 : 2 ** (10 * u - 10),
|
|
186
357
|
easeOutExpo: (u) => u === 1 ? 1 : 1 - 2 ** (-10 * u),
|
|
187
|
-
easeInOutExpo: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? 2 ** (20 * u - 10) / 2 : (2 - 2 ** (-20 * u + 10)) / 2
|
|
358
|
+
easeInOutExpo: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? 2 ** (20 * u - 10) / 2 : (2 - 2 ** (-20 * u + 10)) / 2,
|
|
359
|
+
// --- expressive eases (GSAP's signature feel) — standard Penner equations ---
|
|
360
|
+
// back: overshoots past the target then settles (pop / snap)
|
|
361
|
+
easeInBack: (u) => BACK_C3 * u ** 3 - BACK_C1 * u * u,
|
|
362
|
+
easeOutBack: (u) => 1 + BACK_C3 * (u - 1) ** 3 + BACK_C1 * (u - 1) ** 2,
|
|
363
|
+
easeInOutBack: (u) => u < 0.5 ? (2 * u) ** 2 * ((BACK_C2 + 1) * 2 * u - BACK_C2) / 2 : ((2 * u - 2) ** 2 * ((BACK_C2 + 1) * (2 * u - 2) + BACK_C2) + 2) / 2,
|
|
364
|
+
// elastic: rings around the target before settling (playful spring)
|
|
365
|
+
easeInElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : -(2 ** (10 * u - 10)) * Math.sin((u * 10 - 10.75) * ELASTIC_C4),
|
|
366
|
+
easeOutElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : 2 ** (-10 * u) * Math.sin((u * 10 - 0.75) * ELASTIC_C4) + 1,
|
|
367
|
+
easeInOutElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? -(2 ** (20 * u - 10) * Math.sin((20 * u - 11.125) * ELASTIC_C5)) / 2 : 2 ** (-20 * u + 10) * Math.sin((20 * u - 11.125) * ELASTIC_C5) / 2 + 1,
|
|
368
|
+
// bounce: drops and bounces to rest (lands without overshoot)
|
|
369
|
+
easeInBounce: (u) => 1 - easeOutBounce(1 - u),
|
|
370
|
+
easeOutBounce,
|
|
371
|
+
easeInOutBounce: (u) => u < 0.5 ? (1 - easeOutBounce(1 - 2 * u)) / 2 : (1 + easeOutBounce(2 * u - 1)) / 2
|
|
188
372
|
};
|
|
189
373
|
var EASE_NAMES = Object.keys(EASE_TABLE);
|
|
190
374
|
function resolveEase(ease) {
|
|
@@ -299,6 +483,7 @@
|
|
|
299
483
|
const ops = [];
|
|
300
484
|
const valueAt = (target, prop, fallback) => {
|
|
301
485
|
let value = compiled2.initialValues.get(`${target}.${prop}`) ?? fallback;
|
|
486
|
+
let segStart = Number.NEGATIVE_INFINITY;
|
|
302
487
|
const segs = compiled2.segments.get(`${target}.${prop}`);
|
|
303
488
|
if (segs) {
|
|
304
489
|
let active;
|
|
@@ -307,6 +492,7 @@
|
|
|
307
492
|
else break;
|
|
308
493
|
}
|
|
309
494
|
if (active) {
|
|
495
|
+
segStart = active.t0;
|
|
310
496
|
if (t >= active.t1) {
|
|
311
497
|
value = active.to;
|
|
312
498
|
} else {
|
|
@@ -315,6 +501,23 @@
|
|
|
315
501
|
}
|
|
316
502
|
}
|
|
317
503
|
}
|
|
504
|
+
if (prop === "x" || prop === "y" || prop === "rotation") {
|
|
505
|
+
const drivers = compiled2.motionPaths.get(target);
|
|
506
|
+
if (drivers) {
|
|
507
|
+
let active;
|
|
508
|
+
for (const d of drivers) {
|
|
509
|
+
if (d.t0 <= t) active = d;
|
|
510
|
+
else break;
|
|
511
|
+
}
|
|
512
|
+
if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
|
|
513
|
+
const span = active.t1 - active.t0;
|
|
514
|
+
const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
|
|
515
|
+
if (prop === "x") value = pathPoint(active.points, active.closed, u)[0];
|
|
516
|
+
else if (prop === "y") value = pathPoint(active.points, active.closed, u)[1];
|
|
517
|
+
else value = pathTangentAngle(active.points, active.closed, u) + active.rotateOffset;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
318
521
|
for (const b of compiled2.ir.behaviors ?? []) {
|
|
319
522
|
if (b.target === target && b.prop === prop && typeof value === "number") {
|
|
320
523
|
const envelope = behaviorEnvelope(b, t);
|
|
@@ -412,6 +615,23 @@
|
|
|
412
615
|
});
|
|
413
616
|
return;
|
|
414
617
|
}
|
|
618
|
+
case "path": {
|
|
619
|
+
const ox = num(id, "originX", node.props.originX ?? 0);
|
|
620
|
+
const oy = num(id, "originY", node.props.originY ?? 0);
|
|
621
|
+
const fill = opt(id, "fill", node.props.fill);
|
|
622
|
+
const stroke = opt(id, "stroke", node.props.stroke);
|
|
623
|
+
ops.push({
|
|
624
|
+
type: "path",
|
|
625
|
+
id,
|
|
626
|
+
transform: ox === 0 && oy === 0 ? matrix : multiply(matrix, [1, 0, 0, 1, -ox, -oy]),
|
|
627
|
+
opacity,
|
|
628
|
+
d: str(id, "d", node.props.d),
|
|
629
|
+
progress: Math.max(0, Math.min(1, num(id, "progress", node.props.progress ?? 1))),
|
|
630
|
+
...fill !== void 0 && { fill },
|
|
631
|
+
...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) }
|
|
632
|
+
});
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
415
635
|
case "text": {
|
|
416
636
|
const [ax, ay] = ANCHOR_FACTORS[node.props.anchor ?? "top-left"];
|
|
417
637
|
const raw = valueAt(id, "content", node.props.content);
|
|
@@ -527,6 +747,29 @@
|
|
|
527
747
|
}
|
|
528
748
|
break;
|
|
529
749
|
}
|
|
750
|
+
case "path": {
|
|
751
|
+
const p = new Path2D(op.d);
|
|
752
|
+
if (op.fill) {
|
|
753
|
+
ctx2.fillStyle = op.fill;
|
|
754
|
+
ctx2.fill(p);
|
|
755
|
+
}
|
|
756
|
+
if (op.stroke && (op.strokeWidth ?? 1) > 0) {
|
|
757
|
+
ctx2.strokeStyle = op.stroke;
|
|
758
|
+
ctx2.lineWidth = op.strokeWidth ?? 1;
|
|
759
|
+
ctx2.lineJoin = "round";
|
|
760
|
+
ctx2.lineCap = "round";
|
|
761
|
+
if (op.progress < 1) {
|
|
762
|
+
const len = pathLength(op.d);
|
|
763
|
+
if (len > 0) {
|
|
764
|
+
ctx2.setLineDash([len, len]);
|
|
765
|
+
ctx2.lineDashOffset = len * (1 - op.progress);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
ctx2.stroke(p);
|
|
769
|
+
ctx2.setLineDash([]);
|
|
770
|
+
}
|
|
771
|
+
break;
|
|
772
|
+
}
|
|
530
773
|
case "text": {
|
|
531
774
|
ctx2.font = `${op.fontWeight} ${op.fontSize}px ${quoteFamily(op.fontFamily)}`;
|
|
532
775
|
if (op.letterSpacing) ctx2.letterSpacing = `${op.letterSpacing}px`;
|
|
@@ -544,6 +787,19 @@
|
|
|
544
787
|
function quoteFamily(family) {
|
|
545
788
|
return family.includes(" ") && !family.includes('"') ? `"${family}"` : family;
|
|
546
789
|
}
|
|
790
|
+
var pathLengthCache = /* @__PURE__ */ new Map();
|
|
791
|
+
function pathLength(d) {
|
|
792
|
+
const hit = pathLengthCache.get(d);
|
|
793
|
+
if (hit !== void 0) return hit;
|
|
794
|
+
let len = 0;
|
|
795
|
+
if (typeof document !== "undefined") {
|
|
796
|
+
const el = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
797
|
+
el.setAttribute("d", d);
|
|
798
|
+
len = el.getTotalLength();
|
|
799
|
+
}
|
|
800
|
+
pathLengthCache.set(d, len);
|
|
801
|
+
return len;
|
|
802
|
+
}
|
|
547
803
|
|
|
548
804
|
// ../render-cli/src/browserEntry.ts
|
|
549
805
|
var compiled = null;
|