@sarmal/core 0.24.0 → 0.25.1
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/auto-init.cjs +245 -141
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +244 -140
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.cjs +87 -14
- package/dist/curves/artemis2.cjs.map +1 -1
- package/dist/curves/artemis2.d.cts +1 -5
- package/dist/curves/artemis2.d.ts +1 -5
- package/dist/curves/artemis2.js +86 -13
- package/dist/curves/artemis2.js.map +1 -1
- package/dist/curves/astroid.cjs +4 -4
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/astroid.js +3 -3
- package/dist/curves/deltoid.cjs +4 -4
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/deltoid.js +3 -3
- package/dist/curves/epicycloid3.cjs +4 -4
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epicycloid3.js +3 -3
- package/dist/curves/epitrochoid7.cjs +5 -5
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/epitrochoid7.js +4 -4
- package/dist/curves/index.cjs +154 -71
- package/dist/curves/index.cjs.map +1 -1
- package/dist/curves/index.d.cts +29 -29
- package/dist/curves/index.d.ts +29 -29
- package/dist/curves/index.js +170 -71
- package/dist/curves/index.js.map +1 -1
- package/dist/curves/lame.cjs +6 -5
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lame.js +5 -4
- package/dist/curves/lissajous32.cjs +4 -4
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous32.js +3 -3
- package/dist/curves/lissajous43.cjs +4 -4
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/lissajous43.js +3 -3
- package/dist/curves/rose3.cjs +4 -4
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose3.js +3 -3
- package/dist/curves/rose5.cjs +4 -4
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/curves/rose5.js +3 -3
- package/dist/curves/rose52.cjs +5 -5
- package/dist/curves/rose52.d.cts +1 -1
- package/dist/curves/rose52.d.ts +1 -1
- package/dist/curves/rose52.js +4 -4
- package/dist/curves/star.cjs +8 -5
- package/dist/curves/star.d.cts +1 -1
- package/dist/curves/star.d.ts +1 -1
- package/dist/curves/star.js +7 -4
- package/dist/curves/star4.cjs +8 -5
- package/dist/curves/star4.d.cts +1 -1
- package/dist/curves/star4.d.ts +1 -1
- package/dist/curves/star4.js +7 -4
- package/dist/curves/star7.cjs +8 -5
- package/dist/curves/star7.d.cts +1 -1
- package/dist/curves/star7.d.ts +1 -1
- package/dist/curves/star7.js +7 -4
- package/dist/index.cjs +232 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -36
- package/dist/index.d.ts +106 -36
- package/dist/index.js +252 -172
- package/dist/index.js.map +1 -1
- package/dist/types-Z9i1_AQZ.d.cts +339 -0
- package/dist/types-Z9i1_AQZ.d.ts +339 -0
- package/package.json +1 -1
- package/dist/types-CknrlCAf.d.cts +0 -314
- package/dist/types-CknrlCAf.d.ts +0 -314
package/dist/index.js
CHANGED
|
@@ -61,13 +61,13 @@ function resolveCurve(curveDef) {
|
|
|
61
61
|
period,
|
|
62
62
|
speed,
|
|
63
63
|
skeleton: curveDef.skeleton,
|
|
64
|
-
skeletonFn: curveDef.skeletonFn
|
|
64
|
+
skeletonFn: curveDef.skeletonFn,
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
function createEngine(curveDef, trailLength = 120) {
|
|
68
68
|
if (!Number.isFinite(trailLength) || trailLength <= 0) {
|
|
69
69
|
throw new RangeError(
|
|
70
|
-
`[sarmal] trailLength must be a positive finite number, got ${trailLength}
|
|
70
|
+
`[sarmal] trailLength must be a positive finite number, got ${trailLength}`,
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
let curve = resolveCurve(curveDef);
|
|
@@ -108,7 +108,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
108
108
|
actualTime += deltaTime;
|
|
109
109
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
110
110
|
const a = curve.fn(t, actualTime, EMPTY_PARAMS);
|
|
111
|
-
const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
|
|
111
|
+
const tB = _morphStrategy === "normalized" ? (t / curve.period) * morphCurveB.period : t;
|
|
112
112
|
const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);
|
|
113
113
|
trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
|
|
114
114
|
} else {
|
|
@@ -135,14 +135,14 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
135
135
|
trail.clear();
|
|
136
136
|
},
|
|
137
137
|
jump(newT, { clearTrail = false } = {}) {
|
|
138
|
-
t = (newT % curve.period + curve.period) % curve.period;
|
|
138
|
+
t = ((newT % curve.period) + curve.period) % curve.period;
|
|
139
139
|
if (clearTrail) {
|
|
140
140
|
trail.clear();
|
|
141
141
|
}
|
|
142
142
|
},
|
|
143
143
|
seek(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
|
|
144
144
|
const advance = curve.speed * step;
|
|
145
|
-
const target = (targetT % curve.period + curve.period) % curve.period;
|
|
145
|
+
const target = ((targetT % curve.period) + curve.period) % curve.period;
|
|
146
146
|
const targetTime = target / curve.speed;
|
|
147
147
|
t = target;
|
|
148
148
|
actualTime = targetTime;
|
|
@@ -151,7 +151,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
151
151
|
const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
|
|
152
152
|
for (let i = count - 1; i >= 0; i--) {
|
|
153
153
|
const sampleT = target - i * advance;
|
|
154
|
-
const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
|
|
154
|
+
const wrappedT = ((sampleT % curve.period) + curve.period) % curve.period;
|
|
155
155
|
const time = targetTime - i * step;
|
|
156
156
|
const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
|
|
157
157
|
trail.push(point.x, point.y);
|
|
@@ -168,13 +168,16 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
168
168
|
...frozenB,
|
|
169
169
|
fn: (sampleT, time, params) => {
|
|
170
170
|
const a = frozenA.fn(sampleT, time, params);
|
|
171
|
-
const tB =
|
|
171
|
+
const tB =
|
|
172
|
+
frozenStrategy === "normalized"
|
|
173
|
+
? (sampleT / frozenA.period) * frozenB.period
|
|
174
|
+
: sampleT;
|
|
172
175
|
const b = frozenB.fn(tB, time, params);
|
|
173
176
|
return {
|
|
174
177
|
x: a.x + (b.x - a.x) * frozenAlpha,
|
|
175
|
-
y: a.y + (b.y - a.y) * frozenAlpha
|
|
178
|
+
y: a.y + (b.y - a.y) * frozenAlpha,
|
|
176
179
|
};
|
|
177
|
-
}
|
|
180
|
+
},
|
|
178
181
|
};
|
|
179
182
|
}
|
|
180
183
|
_morphStrategy = strategy;
|
|
@@ -187,7 +190,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
187
190
|
completeMorph() {
|
|
188
191
|
if (morphCurveB !== null) {
|
|
189
192
|
if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
|
|
190
|
-
t = t / curve.period * morphCurveB.period;
|
|
193
|
+
t = (t / curve.period) * morphCurveB.period;
|
|
191
194
|
}
|
|
192
195
|
curve = morphCurveB;
|
|
193
196
|
}
|
|
@@ -196,25 +199,28 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
196
199
|
},
|
|
197
200
|
getSarmalSkeleton() {
|
|
198
201
|
const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);
|
|
199
|
-
const
|
|
202
|
+
const points2 = new Array(steps);
|
|
200
203
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
201
204
|
for (let i = 0; i < steps; i++) {
|
|
202
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
205
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
203
206
|
const a = sampleSkeleton(curve, sampleT);
|
|
204
|
-
const tB =
|
|
207
|
+
const tB =
|
|
208
|
+
_morphStrategy === "normalized"
|
|
209
|
+
? (sampleT / curve.period) * morphCurveB.period
|
|
210
|
+
: sampleT;
|
|
205
211
|
const b = sampleSkeleton(morphCurveB, tB);
|
|
206
|
-
|
|
212
|
+
points2[i] = {
|
|
207
213
|
x: a.x + (b.x - a.x) * _morphAlpha,
|
|
208
|
-
y: a.y + (b.y - a.y) * _morphAlpha
|
|
214
|
+
y: a.y + (b.y - a.y) * _morphAlpha,
|
|
209
215
|
};
|
|
210
216
|
}
|
|
211
|
-
return
|
|
217
|
+
return points2;
|
|
212
218
|
}
|
|
213
219
|
for (let i = 0; i < steps; i++) {
|
|
214
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
215
|
-
|
|
220
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
221
|
+
points2[i] = sampleSkeleton(curve, sampleT);
|
|
216
222
|
}
|
|
217
|
-
return
|
|
223
|
+
return points2;
|
|
218
224
|
},
|
|
219
225
|
setSpeed(speed) {
|
|
220
226
|
if (!Number.isFinite(speed)) {
|
|
@@ -253,7 +259,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
253
259
|
_speedTransition.reject(new Error("Speed transition cancelled"));
|
|
254
260
|
_speedTransition = null;
|
|
255
261
|
}
|
|
256
|
-
}
|
|
262
|
+
},
|
|
257
263
|
};
|
|
258
264
|
}
|
|
259
265
|
|
|
@@ -292,7 +298,15 @@ function computeNormal(trail, i) {
|
|
|
292
298
|
const tangent = computeTangent(trail, i);
|
|
293
299
|
return { x: -tangent.y, y: tangent.x };
|
|
294
300
|
}
|
|
295
|
-
function computeTrailQuad(
|
|
301
|
+
function computeTrailQuad(
|
|
302
|
+
trail,
|
|
303
|
+
i,
|
|
304
|
+
trailCount,
|
|
305
|
+
toX,
|
|
306
|
+
toY,
|
|
307
|
+
minWidth = TRAIL_MIN_WIDTH,
|
|
308
|
+
maxWidth = TRAIL_MAX_WIDTH,
|
|
309
|
+
) {
|
|
296
310
|
const progress = i / (trailCount - 1);
|
|
297
311
|
const nextProgress = (i + 1) / (trailCount - 1);
|
|
298
312
|
const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
|
|
@@ -316,13 +330,16 @@ function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_W
|
|
|
316
330
|
r1x: nx - n1.x * w1,
|
|
317
331
|
r1y: ny - n1.y * w1,
|
|
318
332
|
opacity,
|
|
319
|
-
progress
|
|
333
|
+
progress,
|
|
320
334
|
};
|
|
321
335
|
}
|
|
322
|
-
function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
336
|
+
function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
|
|
323
337
|
if (pts.length === 0) return null;
|
|
324
338
|
const first = pts[0];
|
|
325
|
-
let minX = first.x,
|
|
339
|
+
let minX = first.x,
|
|
340
|
+
maxX = first.x,
|
|
341
|
+
minY = first.y,
|
|
342
|
+
maxY = first.y;
|
|
326
343
|
for (const p of pts) {
|
|
327
344
|
if (p.x < minX) {
|
|
328
345
|
minX = p.x;
|
|
@@ -341,23 +358,23 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
|
341
358
|
const h = maxY - minY;
|
|
342
359
|
if (w === 0 && h === 0) {
|
|
343
360
|
throw new Error(
|
|
344
|
-
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
361
|
+
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t.",
|
|
345
362
|
);
|
|
346
363
|
}
|
|
347
364
|
const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
|
|
348
365
|
const scaleYProportional = logicalHeight / (h * (1 + FIT_PADDING * 2));
|
|
349
|
-
const scaleXMinPadding = (logicalWidth -
|
|
350
|
-
const scaleYMinPadding = (logicalHeight -
|
|
366
|
+
const scaleXMinPadding = (logicalWidth - minPaddingPx * 2) / w;
|
|
367
|
+
const scaleYMinPadding = (logicalHeight - minPaddingPx * 2) / h;
|
|
351
368
|
const scale = Math.min(
|
|
352
369
|
scaleXProportional,
|
|
353
370
|
scaleYProportional,
|
|
354
371
|
scaleXMinPadding,
|
|
355
|
-
scaleYMinPadding
|
|
372
|
+
scaleYMinPadding,
|
|
356
373
|
);
|
|
357
374
|
return {
|
|
358
375
|
scale,
|
|
359
376
|
offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
|
|
360
|
-
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
377
|
+
offsetY: (logicalHeight - h * scale) / 2 - minY * scale,
|
|
361
378
|
};
|
|
362
379
|
}
|
|
363
380
|
function enginePassthroughs(engine) {
|
|
@@ -367,7 +384,8 @@ function enginePassthroughs(engine) {
|
|
|
367
384
|
setSpeed: engine.setSpeed,
|
|
368
385
|
getSpeed: engine.getSpeed,
|
|
369
386
|
resetSpeed: engine.resetSpeed,
|
|
370
|
-
setSpeedOver: engine.setSpeedOver
|
|
387
|
+
setSpeedOver: engine.setSpeedOver,
|
|
388
|
+
getSarmalSkeleton: engine.getSarmalSkeleton,
|
|
371
389
|
};
|
|
372
390
|
}
|
|
373
391
|
var palettes = {
|
|
@@ -376,16 +394,16 @@ var palettes = {
|
|
|
376
394
|
ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
|
|
377
395
|
ice: ["#1e3a8a", "#67e8f9"],
|
|
378
396
|
fire: ["#7f1d1d", "#fbbf24"],
|
|
379
|
-
forest: ["#14532d", "#86efac"]
|
|
397
|
+
forest: ["#14532d", "#86efac"],
|
|
380
398
|
};
|
|
381
399
|
function hexToRgb(hex) {
|
|
382
400
|
const n = parseInt(hex.slice(1), 16);
|
|
383
|
-
return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
|
|
401
|
+
return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };
|
|
384
402
|
}
|
|
385
403
|
var lerpRgb = (a, b, t) => ({
|
|
386
404
|
r: Math.round(a.r + (b.r - a.r) * t),
|
|
387
405
|
g: Math.round(a.g + (b.g - a.g) * t),
|
|
388
|
-
b: Math.round(a.b + (b.b - a.b) * t)
|
|
406
|
+
b: Math.round(a.b + (b.b - a.b) * t),
|
|
389
407
|
});
|
|
390
408
|
function getPaletteColor(palette, position, timeOffset = 0) {
|
|
391
409
|
if (palette.length === 0) {
|
|
@@ -394,7 +412,7 @@ function getPaletteColor(palette, position, timeOffset = 0) {
|
|
|
394
412
|
if (palette.length === 1) {
|
|
395
413
|
return hexToRgb(palette[0]);
|
|
396
414
|
}
|
|
397
|
-
const cyclePos = ((position + timeOffset) % 1 + 1) % 1;
|
|
415
|
+
const cyclePos = (((position + timeOffset) % 1) + 1) % 1;
|
|
398
416
|
const scaled = cyclePos * palette.length;
|
|
399
417
|
const idx = Math.floor(scaled);
|
|
400
418
|
const t = scaled - idx;
|
|
@@ -409,7 +427,7 @@ var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
409
427
|
"headColor",
|
|
410
428
|
"skeletonColor",
|
|
411
429
|
"trailStyle",
|
|
412
|
-
"headRadius"
|
|
430
|
+
"headRadius",
|
|
413
431
|
]);
|
|
414
432
|
function validateRenderOptions(partial) {
|
|
415
433
|
for (const key of Object.keys(partial)) {
|
|
@@ -437,7 +455,7 @@ function assertTrailColor(value) {
|
|
|
437
455
|
if (typeof value === "string") {
|
|
438
456
|
if (!HEX_COLOR_RE.test(value)) {
|
|
439
457
|
throw new TypeError(
|
|
440
|
-
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"
|
|
458
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`,
|
|
441
459
|
);
|
|
442
460
|
}
|
|
443
461
|
return;
|
|
@@ -445,21 +463,21 @@ function assertTrailColor(value) {
|
|
|
445
463
|
if (Array.isArray(value)) {
|
|
446
464
|
if (value.length < 2) {
|
|
447
465
|
throw new RangeError(
|
|
448
|
-
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}
|
|
466
|
+
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`,
|
|
449
467
|
);
|
|
450
468
|
}
|
|
451
469
|
for (let i = 0; i < value.length; i++) {
|
|
452
470
|
const entry = value[i];
|
|
453
471
|
if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
|
|
454
472
|
throw new TypeError(
|
|
455
|
-
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}
|
|
473
|
+
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`,
|
|
456
474
|
);
|
|
457
475
|
}
|
|
458
476
|
}
|
|
459
477
|
return;
|
|
460
478
|
}
|
|
461
479
|
throw new TypeError(
|
|
462
|
-
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}
|
|
480
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`,
|
|
463
481
|
);
|
|
464
482
|
}
|
|
465
483
|
function assertHeadColor(value) {
|
|
@@ -468,7 +486,7 @@ function assertHeadColor(value) {
|
|
|
468
486
|
}
|
|
469
487
|
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
470
488
|
throw new TypeError(
|
|
471
|
-
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}
|
|
489
|
+
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`,
|
|
472
490
|
);
|
|
473
491
|
}
|
|
474
492
|
}
|
|
@@ -478,26 +496,26 @@ function assertSkeletonColor(value) {
|
|
|
478
496
|
}
|
|
479
497
|
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
480
498
|
throw new TypeError(
|
|
481
|
-
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}
|
|
499
|
+
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`,
|
|
482
500
|
);
|
|
483
501
|
}
|
|
484
502
|
}
|
|
485
503
|
function assertTrailStyle(value) {
|
|
486
504
|
if (!TRAIL_STYLES.includes(value)) {
|
|
487
505
|
throw new RangeError(
|
|
488
|
-
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}
|
|
506
|
+
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`,
|
|
489
507
|
);
|
|
490
508
|
}
|
|
491
509
|
}
|
|
492
510
|
function assertHeadRadius(value) {
|
|
493
511
|
if (typeof value !== "number") {
|
|
494
512
|
throw new TypeError(
|
|
495
|
-
`[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}
|
|
513
|
+
`[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`,
|
|
496
514
|
);
|
|
497
515
|
}
|
|
498
516
|
if (!Number.isFinite(value) || value <= 0) {
|
|
499
517
|
throw new TypeError(
|
|
500
|
-
`[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}
|
|
518
|
+
`[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`,
|
|
501
519
|
);
|
|
502
520
|
}
|
|
503
521
|
}
|
|
@@ -519,13 +537,13 @@ function resolveHeadColor(trailColor, trailStyle) {
|
|
|
519
537
|
function warnIfTrailColorMismatch(trailColor, trailStyle) {
|
|
520
538
|
if (trailStyle === "default" && Array.isArray(trailColor)) {
|
|
521
539
|
console.warn(
|
|
522
|
-
'[sarmal] trailColor is an array but trailStyle is "default"; only the first color will be used. Pass a gradient trailStyle to use the whole palette.'
|
|
540
|
+
'[sarmal] trailColor is an array but trailStyle is "default"; only the first color will be used. Pass a gradient trailStyle to use the whole palette.',
|
|
523
541
|
);
|
|
524
542
|
return;
|
|
525
543
|
}
|
|
526
544
|
if (trailStyle !== "default" && typeof trailColor === "string") {
|
|
527
545
|
console.warn(
|
|
528
|
-
`[sarmal] trailColor is a single color but trailStyle is "${trailStyle}"; the trail will render as a solid color. Pass an array of hex colors to use a real gradient
|
|
546
|
+
`[sarmal] trailColor is a single color but trailStyle is "${trailStyle}"; the trail will render as a solid color. Pass an array of hex colors to use a real gradient.`,
|
|
529
547
|
);
|
|
530
548
|
}
|
|
531
549
|
}
|
|
@@ -535,7 +553,7 @@ var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160)
|
|
|
535
553
|
var WHITE_HEX = "#ffffff";
|
|
536
554
|
function hexToRgbComponents(hex) {
|
|
537
555
|
const n = parseInt(hex.slice(1), 16);
|
|
538
|
-
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
556
|
+
return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
|
|
539
557
|
}
|
|
540
558
|
function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
|
|
541
559
|
target.style.width = `${logicalWidth}px`;
|
|
@@ -662,7 +680,7 @@ function createRenderer(options) {
|
|
|
662
680
|
i,
|
|
663
681
|
trailCount,
|
|
664
682
|
toX,
|
|
665
|
-
toY
|
|
683
|
+
toY,
|
|
666
684
|
);
|
|
667
685
|
if (trailStyle === "default") {
|
|
668
686
|
ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
|
|
@@ -827,7 +845,7 @@ function createRenderer(options) {
|
|
|
827
845
|
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
828
846
|
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
829
847
|
}
|
|
830
|
-
}
|
|
848
|
+
},
|
|
831
849
|
};
|
|
832
850
|
const pauseOnHidden = options.pauseOnHidden !== false;
|
|
833
851
|
function handleVisibilityChange() {
|
|
@@ -877,7 +895,7 @@ function sampleCurveSkeleton(curveDef) {
|
|
|
877
895
|
const samples = Math.ceil(period * 50);
|
|
878
896
|
const pts = Array.from({ length: samples });
|
|
879
897
|
for (let i = 0; i < samples; i++) {
|
|
880
|
-
const t = i / (samples - 1) * period;
|
|
898
|
+
const t = (i / (samples - 1)) * period;
|
|
881
899
|
pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS2);
|
|
882
900
|
}
|
|
883
901
|
return pts;
|
|
@@ -890,7 +908,7 @@ function createSVGRenderer(options) {
|
|
|
890
908
|
const poolSize = engine.trailLength;
|
|
891
909
|
if (poolSize > HIGH_TRAIL_LENGTH_THRESHOLD) {
|
|
892
910
|
console.warn(
|
|
893
|
-
`[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails
|
|
911
|
+
`[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails.`,
|
|
894
912
|
);
|
|
895
913
|
}
|
|
896
914
|
let trailStyle = options.trailStyle ?? "default";
|
|
@@ -909,9 +927,9 @@ function createSVGRenderer(options) {
|
|
|
909
927
|
return rect.width && rect.height ? Math.min(rect.width, rect.height) : 200;
|
|
910
928
|
}
|
|
911
929
|
const containerPx = getContainerPixelSize();
|
|
912
|
-
const svgTrailMinWidth = TRAIL_MIN_WIDTH * viewSize / containerPx;
|
|
913
|
-
const svgTrailMaxWidth = TRAIL_MAX_WIDTH * viewSize / containerPx;
|
|
914
|
-
const svgSkeletonStrokeWidth = String(SKELETON_STROKE_WIDTH_PX * viewSize / containerPx);
|
|
930
|
+
const svgTrailMinWidth = (TRAIL_MIN_WIDTH * viewSize) / containerPx;
|
|
931
|
+
const svgTrailMaxWidth = (TRAIL_MAX_WIDTH * viewSize) / containerPx;
|
|
932
|
+
const svgSkeletonStrokeWidth = String((SKELETON_STROKE_WIDTH_PX * viewSize) / containerPx);
|
|
915
933
|
headRadius = options.headRadius ?? SVG_DEFAULT_HEAD_RADIUS;
|
|
916
934
|
container.setAttribute("viewBox", `0 0 ${viewSize} ${viewSize}`);
|
|
917
935
|
container.setAttribute("role", "img");
|
|
@@ -999,7 +1017,7 @@ function createSVGRenderer(options) {
|
|
|
999
1017
|
px,
|
|
1000
1018
|
py,
|
|
1001
1019
|
svgTrailMinWidth,
|
|
1002
|
-
svgTrailMaxWidth
|
|
1020
|
+
svgTrailMaxWidth,
|
|
1003
1021
|
);
|
|
1004
1022
|
const d = `M${l0x.toFixed(2)} ${l0y.toFixed(2)} L${l1x.toFixed(2)} ${l1y.toFixed(2)} L${r1x.toFixed(2)} ${r1y.toFixed(2)} L${r0x.toFixed(2)} ${r0y.toFixed(2)} Z`;
|
|
1005
1023
|
trailPaths[i].setAttribute("d", d);
|
|
@@ -1027,7 +1045,8 @@ function createSVGRenderer(options) {
|
|
|
1027
1045
|
let animationId = null;
|
|
1028
1046
|
let lastTime = 0;
|
|
1029
1047
|
let pausedByVisibility = false;
|
|
1030
|
-
const prefersReducedMotion =
|
|
1048
|
+
const prefersReducedMotion =
|
|
1049
|
+
typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1031
1050
|
let morphResolve = null;
|
|
1032
1051
|
let morphReject = null;
|
|
1033
1052
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
@@ -1045,7 +1064,7 @@ function createSVGRenderer(options) {
|
|
|
1045
1064
|
skeletonPathA.setAttribute("visibility", "visible");
|
|
1046
1065
|
skeletonPathA.setAttribute(
|
|
1047
1066
|
"stroke-opacity",
|
|
1048
|
-
String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
|
|
1067
|
+
String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY),
|
|
1049
1068
|
);
|
|
1050
1069
|
}
|
|
1051
1070
|
if (morphPathBBuilt) {
|
|
@@ -1199,7 +1218,7 @@ function createSVGRenderer(options) {
|
|
|
1199
1218
|
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
1200
1219
|
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
1201
1220
|
}
|
|
1202
|
-
}
|
|
1221
|
+
},
|
|
1203
1222
|
};
|
|
1204
1223
|
const pauseOnHidden = options.pauseOnHidden !== false;
|
|
1205
1224
|
function handleVisibilityChange() {
|
|
@@ -1232,241 +1251,324 @@ function createSarmalSVG(container, curveDef, options) {
|
|
|
1232
1251
|
return createSVGRenderer({ container, engine, ...rendererOpts });
|
|
1233
1252
|
}
|
|
1234
1253
|
|
|
1235
|
-
// src/
|
|
1236
|
-
var
|
|
1237
|
-
function
|
|
1238
|
-
const
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1254
|
+
// src/catmull-rom.ts
|
|
1255
|
+
var PERIOD = 2 * Math.PI;
|
|
1256
|
+
function catmullRom1D(p0, p1, p2, p3, u) {
|
|
1257
|
+
const u2 = u * u;
|
|
1258
|
+
const u3 = u2 * u;
|
|
1259
|
+
return (
|
|
1260
|
+
0.5 *
|
|
1261
|
+
(2 * p1 +
|
|
1262
|
+
(-p0 + p2) * u +
|
|
1263
|
+
(2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 +
|
|
1264
|
+
(-p0 + 3 * p1 - 3 * p2 + p3) * u3)
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
function evaluateCatmullRom(points2, t) {
|
|
1268
|
+
const N = points2.length;
|
|
1269
|
+
if (N === 0) {
|
|
1270
|
+
return { x: 0, y: 0 };
|
|
1271
|
+
}
|
|
1272
|
+
if (N === 1) {
|
|
1273
|
+
return { x: points2[0][0], y: points2[0][1] };
|
|
1274
|
+
}
|
|
1275
|
+
t = ((t % PERIOD) + PERIOD) % PERIOD;
|
|
1276
|
+
const segmentSize = PERIOD / N;
|
|
1277
|
+
let i = Math.floor(t / segmentSize);
|
|
1278
|
+
if (i >= N) {
|
|
1279
|
+
i = N - 1;
|
|
1280
|
+
}
|
|
1281
|
+
let u = (t - i * segmentSize) / segmentSize;
|
|
1282
|
+
u = Math.max(0, Math.min(1, u));
|
|
1283
|
+
const p0 = points2[(i - 1 + N) % N];
|
|
1284
|
+
const p1 = points2[i];
|
|
1285
|
+
const p2 = points2[(i + 1) % N];
|
|
1286
|
+
const p3 = points2[(i + 2) % N];
|
|
1241
1287
|
return {
|
|
1242
|
-
x:
|
|
1243
|
-
y:
|
|
1288
|
+
x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
|
|
1289
|
+
y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u),
|
|
1244
1290
|
};
|
|
1245
1291
|
}
|
|
1292
|
+
function drawCurve(points2, opts) {
|
|
1293
|
+
if (points2.length < 3) {
|
|
1294
|
+
throw new Error(`drawCurve requires at least 3 points, received ${points2.length}.`);
|
|
1295
|
+
}
|
|
1296
|
+
const first = points2[0];
|
|
1297
|
+
if (points2.every((p) => p[0] === first[0] && p[1] === first[1])) {
|
|
1298
|
+
console.warn(
|
|
1299
|
+
"[sarmal].drawCurve: all control points are identical. The curve will be a single point.",
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
const maxAbs = points2.reduce((m, p) => Math.max(m, Math.abs(p[0]), Math.abs(p[1])), 0);
|
|
1303
|
+
if (maxAbs > 2) {
|
|
1304
|
+
console.warn(
|
|
1305
|
+
`[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`,
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
const pts = points2.map(([x, y]) => [x, y]);
|
|
1309
|
+
return {
|
|
1310
|
+
name: opts?.name ?? "drawn",
|
|
1311
|
+
fn: (t) => evaluateCatmullRom(pts, t),
|
|
1312
|
+
period: PERIOD,
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// src/curves/artemis2.ts
|
|
1317
|
+
var points = [
|
|
1318
|
+
[-0.44, -0.45],
|
|
1319
|
+
[-0.53, -0.77],
|
|
1320
|
+
[-0.82, -0.66],
|
|
1321
|
+
[-0.82, -0.18],
|
|
1322
|
+
[-0.25, -0.04],
|
|
1323
|
+
[0.16, -0.49],
|
|
1324
|
+
[-0.03, -0.87],
|
|
1325
|
+
[-0.68, -0.94],
|
|
1326
|
+
[-0.95, -0.61],
|
|
1327
|
+
[-0.87, -0],
|
|
1328
|
+
[-0.34, 0.21],
|
|
1329
|
+
[0.27, -0.04],
|
|
1330
|
+
[0.87, 0.06],
|
|
1331
|
+
[0.87, 0.57],
|
|
1332
|
+
[0.32, 0.66],
|
|
1333
|
+
[-0.21, -0.43],
|
|
1334
|
+
[-0.43, -0.81],
|
|
1335
|
+
[-0.69, -0.84],
|
|
1336
|
+
[-0.87, -0.66],
|
|
1337
|
+
[-0.9, -0.47],
|
|
1338
|
+
[-0.76, -0.35],
|
|
1339
|
+
];
|
|
1246
1340
|
var artemis2 = {
|
|
1247
|
-
name: "Artemis II",
|
|
1248
|
-
|
|
1249
|
-
period: TWO_PI2,
|
|
1250
|
-
speed: 0.7
|
|
1341
|
+
...drawCurve(points, { name: "Artemis II" }),
|
|
1342
|
+
speed: 0.7,
|
|
1251
1343
|
};
|
|
1252
1344
|
|
|
1253
1345
|
// src/curves/astroid.ts
|
|
1254
|
-
var
|
|
1346
|
+
var TWO_PI2 = Math.PI * 2;
|
|
1255
1347
|
function astroidFn(t, _time, _params) {
|
|
1256
1348
|
const c = Math.cos(t);
|
|
1257
1349
|
const s = Math.sin(t);
|
|
1258
1350
|
return {
|
|
1259
1351
|
x: c * c * c,
|
|
1260
|
-
y: s * s * s
|
|
1352
|
+
y: s * s * s,
|
|
1261
1353
|
};
|
|
1262
1354
|
}
|
|
1263
1355
|
var astroid = {
|
|
1264
1356
|
name: "Astroid",
|
|
1265
1357
|
fn: astroidFn,
|
|
1266
|
-
period:
|
|
1267
|
-
speed: 1.1
|
|
1358
|
+
period: TWO_PI2,
|
|
1359
|
+
speed: 1.1,
|
|
1268
1360
|
};
|
|
1269
1361
|
|
|
1270
1362
|
// src/curves/deltoid.ts
|
|
1271
|
-
var
|
|
1363
|
+
var TWO_PI3 = Math.PI * 2;
|
|
1272
1364
|
function deltoidFn(t, _time, _params) {
|
|
1273
1365
|
return {
|
|
1274
1366
|
x: 2 * Math.cos(t) + Math.cos(2 * t),
|
|
1275
|
-
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
1367
|
+
y: 2 * Math.sin(t) - Math.sin(2 * t),
|
|
1276
1368
|
};
|
|
1277
1369
|
}
|
|
1278
1370
|
var deltoid = {
|
|
1279
1371
|
name: "Deltoid",
|
|
1280
1372
|
fn: deltoidFn,
|
|
1281
|
-
period:
|
|
1282
|
-
speed: 0.9
|
|
1373
|
+
period: TWO_PI3,
|
|
1374
|
+
speed: 0.9,
|
|
1283
1375
|
};
|
|
1284
1376
|
|
|
1285
1377
|
// src/curves/epicycloid3.ts
|
|
1286
|
-
var
|
|
1378
|
+
var TWO_PI4 = Math.PI * 2;
|
|
1287
1379
|
function epicycloid3Fn(t, _time, _params) {
|
|
1288
1380
|
return {
|
|
1289
1381
|
x: 4 * Math.cos(t) - Math.cos(4 * t),
|
|
1290
|
-
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
1382
|
+
y: 4 * Math.sin(t) - Math.sin(4 * t),
|
|
1291
1383
|
};
|
|
1292
1384
|
}
|
|
1293
1385
|
var epicycloid3 = {
|
|
1294
1386
|
name: "Epicycloid (n=3)",
|
|
1295
1387
|
fn: epicycloid3Fn,
|
|
1296
|
-
period:
|
|
1297
|
-
speed: 0.75
|
|
1388
|
+
period: TWO_PI4,
|
|
1389
|
+
speed: 0.75,
|
|
1298
1390
|
};
|
|
1299
1391
|
|
|
1300
1392
|
// src/curves/epitrochoid7.ts
|
|
1301
|
-
var
|
|
1393
|
+
var TWO_PI5 = Math.PI * 2;
|
|
1302
1394
|
function epitrochoid7Fn(t, _time, _params) {
|
|
1303
1395
|
const d = 1 + 0.55 * Math.sin(t * 0.5);
|
|
1304
1396
|
return {
|
|
1305
1397
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
1306
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1398
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
1307
1399
|
};
|
|
1308
1400
|
}
|
|
1309
1401
|
function epitrochoid7SkeletonFn(t) {
|
|
1310
1402
|
const d = 1.275;
|
|
1311
1403
|
return {
|
|
1312
1404
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
1313
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1405
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
1314
1406
|
};
|
|
1315
1407
|
}
|
|
1316
1408
|
var epitrochoid7 = {
|
|
1317
1409
|
name: "Epitrochoid",
|
|
1318
1410
|
fn: epitrochoid7Fn,
|
|
1319
|
-
period:
|
|
1411
|
+
period: TWO_PI5,
|
|
1320
1412
|
speed: 1.4,
|
|
1321
|
-
skeletonFn: epitrochoid7SkeletonFn
|
|
1413
|
+
skeletonFn: epitrochoid7SkeletonFn,
|
|
1322
1414
|
};
|
|
1323
1415
|
|
|
1324
1416
|
// src/curves/lissajous32.ts
|
|
1325
|
-
var
|
|
1417
|
+
var TWO_PI6 = Math.PI * 2;
|
|
1326
1418
|
function lissajous32Fn(t, time, _params) {
|
|
1327
1419
|
const phi = time * 0.45;
|
|
1328
1420
|
return {
|
|
1329
1421
|
x: Math.sin(3 * t + phi),
|
|
1330
|
-
y: Math.sin(2 * t)
|
|
1422
|
+
y: Math.sin(2 * t),
|
|
1331
1423
|
};
|
|
1332
1424
|
}
|
|
1333
1425
|
var lissajous32 = {
|
|
1334
1426
|
name: "Lissajous 3:2",
|
|
1335
1427
|
fn: lissajous32Fn,
|
|
1336
|
-
period:
|
|
1428
|
+
period: TWO_PI6,
|
|
1337
1429
|
speed: 2,
|
|
1338
|
-
skeleton: "live"
|
|
1430
|
+
skeleton: "live",
|
|
1339
1431
|
};
|
|
1340
1432
|
|
|
1341
1433
|
// src/curves/lissajous43.ts
|
|
1342
|
-
var
|
|
1434
|
+
var TWO_PI7 = Math.PI * 2;
|
|
1343
1435
|
function lissajous43Fn(t, time, _params) {
|
|
1344
1436
|
const phi = time * 0.38;
|
|
1345
1437
|
return {
|
|
1346
1438
|
x: Math.sin(4 * t + phi),
|
|
1347
|
-
y: Math.sin(3 * t)
|
|
1439
|
+
y: Math.sin(3 * t),
|
|
1348
1440
|
};
|
|
1349
1441
|
}
|
|
1350
1442
|
var lissajous43 = {
|
|
1351
1443
|
name: "Lissajous 4:3",
|
|
1352
1444
|
fn: lissajous43Fn,
|
|
1353
|
-
period:
|
|
1445
|
+
period: TWO_PI7,
|
|
1354
1446
|
speed: 1.8,
|
|
1355
|
-
skeleton: "live"
|
|
1447
|
+
skeleton: "live",
|
|
1356
1448
|
};
|
|
1357
1449
|
|
|
1358
1450
|
// src/curves/lame.ts
|
|
1359
|
-
var
|
|
1451
|
+
var TWO_PI8 = Math.PI * 2;
|
|
1360
1452
|
function lameFn(t, time, _params) {
|
|
1361
1453
|
const p = 1.75 + 1.25 * Math.sin(time * 0.48);
|
|
1362
|
-
const c = Math.cos(t),
|
|
1454
|
+
const c = Math.cos(t),
|
|
1455
|
+
s = Math.sin(t);
|
|
1363
1456
|
return {
|
|
1364
1457
|
x: Math.sign(c) * Math.pow(Math.abs(c), p),
|
|
1365
|
-
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
1458
|
+
y: Math.sign(s) * Math.pow(Math.abs(s), p),
|
|
1366
1459
|
};
|
|
1367
1460
|
}
|
|
1368
1461
|
var lame = {
|
|
1369
1462
|
name: "Lam\xE9 Curve",
|
|
1370
1463
|
fn: lameFn,
|
|
1371
|
-
period:
|
|
1464
|
+
period: TWO_PI8,
|
|
1372
1465
|
speed: 1,
|
|
1373
|
-
skeleton: "live"
|
|
1466
|
+
skeleton: "live",
|
|
1374
1467
|
};
|
|
1375
1468
|
|
|
1376
1469
|
// src/curves/rose3.ts
|
|
1377
|
-
var
|
|
1470
|
+
var TWO_PI9 = Math.PI * 2;
|
|
1378
1471
|
function rose3Fn(t, _time, _params) {
|
|
1379
1472
|
const r = Math.cos(3 * t);
|
|
1380
1473
|
return {
|
|
1381
1474
|
x: r * Math.cos(t),
|
|
1382
|
-
y: r * Math.sin(t)
|
|
1475
|
+
y: r * Math.sin(t),
|
|
1383
1476
|
};
|
|
1384
1477
|
}
|
|
1385
1478
|
var rose3 = {
|
|
1386
1479
|
name: "Rose (n=3)",
|
|
1387
1480
|
fn: rose3Fn,
|
|
1388
|
-
period:
|
|
1389
|
-
speed: 1.15
|
|
1481
|
+
period: TWO_PI9,
|
|
1482
|
+
speed: 1.15,
|
|
1390
1483
|
};
|
|
1391
1484
|
|
|
1392
1485
|
// src/curves/rose5.ts
|
|
1393
|
-
var
|
|
1486
|
+
var TWO_PI10 = Math.PI * 2;
|
|
1394
1487
|
function rose5Fn(t, _time, _params) {
|
|
1395
1488
|
const r = Math.cos(5 * t);
|
|
1396
1489
|
return {
|
|
1397
1490
|
x: r * Math.cos(t),
|
|
1398
|
-
y: r * Math.sin(t)
|
|
1491
|
+
y: r * Math.sin(t),
|
|
1399
1492
|
};
|
|
1400
1493
|
}
|
|
1401
1494
|
var rose5 = {
|
|
1402
1495
|
name: "Rose (n=5)",
|
|
1403
1496
|
fn: rose5Fn,
|
|
1404
|
-
period:
|
|
1405
|
-
speed: 1
|
|
1497
|
+
period: TWO_PI10,
|
|
1498
|
+
speed: 1,
|
|
1406
1499
|
};
|
|
1407
1500
|
|
|
1408
1501
|
// src/curves/rose52.ts
|
|
1409
1502
|
var FOUR_PI = Math.PI * 4;
|
|
1410
1503
|
function rose52Fn(t, _time, _params) {
|
|
1411
|
-
const r = Math.cos(5 / 2 * t);
|
|
1504
|
+
const r = Math.cos((5 / 2) * t);
|
|
1412
1505
|
return {
|
|
1413
1506
|
x: r * Math.cos(t),
|
|
1414
|
-
y: r * Math.sin(t)
|
|
1507
|
+
y: r * Math.sin(t),
|
|
1415
1508
|
};
|
|
1416
1509
|
}
|
|
1417
1510
|
var rose52 = {
|
|
1418
1511
|
name: "Rose (n=5/2)",
|
|
1419
1512
|
fn: rose52Fn,
|
|
1420
1513
|
period: FOUR_PI,
|
|
1421
|
-
speed: 0.8
|
|
1514
|
+
speed: 0.8,
|
|
1422
1515
|
};
|
|
1423
1516
|
|
|
1424
1517
|
// src/curves/star.ts
|
|
1425
|
-
var
|
|
1518
|
+
var TWO_PI11 = Math.PI * 2;
|
|
1426
1519
|
function starFn(t, _time, _params) {
|
|
1427
|
-
const r =
|
|
1520
|
+
const r =
|
|
1521
|
+
Math.abs(Math.cos((5 / 2) * t)) +
|
|
1522
|
+
0.35 * Math.abs(Math.cos((15 / 2) * t)) +
|
|
1523
|
+
0.15 * Math.abs(Math.cos((25 / 2) * t));
|
|
1428
1524
|
return {
|
|
1429
1525
|
x: r * Math.cos(t),
|
|
1430
|
-
y: r * Math.sin(t)
|
|
1526
|
+
y: r * Math.sin(t),
|
|
1431
1527
|
};
|
|
1432
1528
|
}
|
|
1433
1529
|
var star = {
|
|
1434
1530
|
name: "Star",
|
|
1435
1531
|
fn: starFn,
|
|
1436
|
-
period:
|
|
1437
|
-
speed: 1
|
|
1532
|
+
period: TWO_PI11,
|
|
1533
|
+
speed: 1,
|
|
1438
1534
|
};
|
|
1439
1535
|
|
|
1440
1536
|
// src/curves/star4.ts
|
|
1441
|
-
var
|
|
1537
|
+
var TWO_PI12 = Math.PI * 2;
|
|
1442
1538
|
function star4Fn(t, _time, _params) {
|
|
1443
|
-
const r =
|
|
1539
|
+
const r =
|
|
1540
|
+
Math.abs(Math.cos(2 * t)) +
|
|
1541
|
+
0.35 * Math.abs(Math.cos(6 * t)) +
|
|
1542
|
+
0.15 * Math.abs(Math.cos(10 * t));
|
|
1444
1543
|
return {
|
|
1445
1544
|
x: r * Math.cos(t),
|
|
1446
|
-
y: r * Math.sin(t)
|
|
1545
|
+
y: r * Math.sin(t),
|
|
1447
1546
|
};
|
|
1448
1547
|
}
|
|
1449
1548
|
var star4 = {
|
|
1450
1549
|
name: "Star (4-arm)",
|
|
1451
1550
|
fn: star4Fn,
|
|
1452
|
-
period:
|
|
1453
|
-
speed: 1
|
|
1551
|
+
period: TWO_PI12,
|
|
1552
|
+
speed: 1,
|
|
1454
1553
|
};
|
|
1455
1554
|
|
|
1456
1555
|
// src/curves/star7.ts
|
|
1457
|
-
var
|
|
1556
|
+
var TWO_PI13 = Math.PI * 2;
|
|
1458
1557
|
function star7Fn(t, _time, _params) {
|
|
1459
|
-
const r =
|
|
1558
|
+
const r =
|
|
1559
|
+
Math.abs(Math.cos((7 / 2) * t)) +
|
|
1560
|
+
0.35 * Math.abs(Math.cos((21 / 2) * t)) +
|
|
1561
|
+
0.15 * Math.abs(Math.cos((35 / 2) * t));
|
|
1460
1562
|
return {
|
|
1461
1563
|
x: r * Math.cos(t),
|
|
1462
|
-
y: r * Math.sin(t)
|
|
1564
|
+
y: r * Math.sin(t),
|
|
1463
1565
|
};
|
|
1464
1566
|
}
|
|
1465
1567
|
var star7 = {
|
|
1466
1568
|
name: "Star (7-arm)",
|
|
1467
1569
|
fn: star7Fn,
|
|
1468
|
-
period:
|
|
1469
|
-
speed: 1
|
|
1570
|
+
period: TWO_PI13,
|
|
1571
|
+
speed: 1,
|
|
1470
1572
|
};
|
|
1471
1573
|
|
|
1472
1574
|
// src/curves/index.ts
|
|
@@ -1484,52 +1586,9 @@ var curves = {
|
|
|
1484
1586
|
lissajous32,
|
|
1485
1587
|
lissajous43,
|
|
1486
1588
|
epicycloid3,
|
|
1487
|
-
lame
|
|
1589
|
+
lame,
|
|
1488
1590
|
};
|
|
1489
1591
|
|
|
1490
|
-
// src/catmull-rom.ts
|
|
1491
|
-
var PERIOD = 2 * Math.PI;
|
|
1492
|
-
function catmullRom1D(p0, p1, p2, p3, u) {
|
|
1493
|
-
const u2 = u * u;
|
|
1494
|
-
const u3 = u2 * u;
|
|
1495
|
-
return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
|
|
1496
|
-
}
|
|
1497
|
-
function evaluateCatmullRom(points, t) {
|
|
1498
|
-
const N = points.length;
|
|
1499
|
-
if (N === 0) {
|
|
1500
|
-
return { x: 0, y: 0 };
|
|
1501
|
-
}
|
|
1502
|
-
if (N === 1) {
|
|
1503
|
-
return { x: points[0][0], y: points[0][1] };
|
|
1504
|
-
}
|
|
1505
|
-
t = (t % PERIOD + PERIOD) % PERIOD;
|
|
1506
|
-
const segmentSize = PERIOD / N;
|
|
1507
|
-
let i = Math.floor(t / segmentSize);
|
|
1508
|
-
if (i >= N) {
|
|
1509
|
-
i = N - 1;
|
|
1510
|
-
}
|
|
1511
|
-
let u = (t - i * segmentSize) / segmentSize;
|
|
1512
|
-
u = Math.max(0, Math.min(1, u));
|
|
1513
|
-
const p0 = points[(i - 1 + N) % N];
|
|
1514
|
-
const p1 = points[i];
|
|
1515
|
-
const p2 = points[(i + 1) % N];
|
|
1516
|
-
const p3 = points[(i + 2) % N];
|
|
1517
|
-
return {
|
|
1518
|
-
x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
|
|
1519
|
-
y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
|
|
1520
|
-
};
|
|
1521
|
-
}
|
|
1522
|
-
function drawCurve(points) {
|
|
1523
|
-
if (points.length < 3) {
|
|
1524
|
-
throw new Error(`drawCurve requires at least 3 points, received ${points.length}.`);
|
|
1525
|
-
}
|
|
1526
|
-
return {
|
|
1527
|
-
name: "custom",
|
|
1528
|
-
fn: (t) => evaluateCatmullRom(points, t),
|
|
1529
|
-
period: PERIOD
|
|
1530
|
-
};
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
1592
|
// src/index.ts
|
|
1534
1593
|
function createSarmal(canvas, curveDef, options) {
|
|
1535
1594
|
const { trailLength, ...rendererOpts } = options ?? {};
|
|
@@ -1537,6 +1596,27 @@ function createSarmal(canvas, curveDef, options) {
|
|
|
1537
1596
|
return createRenderer({ canvas, engine, ...rendererOpts });
|
|
1538
1597
|
}
|
|
1539
1598
|
|
|
1540
|
-
export {
|
|
1599
|
+
export {
|
|
1600
|
+
artemis2,
|
|
1601
|
+
astroid,
|
|
1602
|
+
computeBoundaries,
|
|
1603
|
+
createEngine,
|
|
1604
|
+
createRenderer,
|
|
1605
|
+
createSVGRenderer,
|
|
1606
|
+
createSarmal,
|
|
1607
|
+
createSarmalSVG,
|
|
1608
|
+
curves,
|
|
1609
|
+
deltoid,
|
|
1610
|
+
drawCurve,
|
|
1611
|
+
epicycloid3,
|
|
1612
|
+
epitrochoid7,
|
|
1613
|
+
evaluateCatmullRom,
|
|
1614
|
+
lame,
|
|
1615
|
+
lissajous32,
|
|
1616
|
+
lissajous43,
|
|
1617
|
+
palettes,
|
|
1618
|
+
rose3,
|
|
1619
|
+
rose5,
|
|
1620
|
+
};
|
|
1621
|
+
//# sourceMappingURL=index.js.map
|
|
1541
1622
|
//# sourceMappingURL=index.js.map
|
|
1542
|
-
//# sourceMappingURL=index.js.map
|