@sarmal/core 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-init.cjs +255 -175
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +254 -174
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.cjs +82 -17
- 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 +81 -16
- 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 +139 -84
- 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 +139 -100
- package/dist/curves/index.js.map +1 -1
- package/dist/curves/lame.cjs +5 -6
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lame.js +4 -5
- 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 +5 -8
- package/dist/curves/star.d.cts +1 -1
- package/dist/curves/star.d.ts +1 -1
- package/dist/curves/star.js +4 -7
- package/dist/curves/star4.cjs +5 -8
- package/dist/curves/star4.d.cts +1 -1
- package/dist/curves/star4.d.ts +1 -1
- package/dist/curves/star4.js +4 -7
- package/dist/curves/star7.cjs +5 -8
- package/dist/curves/star7.d.cts +1 -1
- package/dist/curves/star7.d.ts +1 -1
- package/dist/curves/star7.js +4 -7
- package/dist/index.cjs +244 -210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -78
- package/dist/index.d.ts +55 -78
- package/dist/index.js +243 -230
- package/dist/index.js.map +1 -1
- package/dist/types-BZpzgNau.d.cts +332 -0
- package/dist/types-BZpzgNau.d.ts +332 -0
- package/package.json +1 -1
- package/dist/types-C0b4MPtI.d.cts +0 -321
- package/dist/types-C0b4MPtI.d.ts +0 -321
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/engine.ts
|
|
4
4
|
var TWO_PI = Math.PI * 2;
|
|
@@ -63,13 +63,13 @@ function resolveCurve(curveDef) {
|
|
|
63
63
|
period,
|
|
64
64
|
speed,
|
|
65
65
|
skeleton: curveDef.skeleton,
|
|
66
|
-
skeletonFn: curveDef.skeletonFn
|
|
66
|
+
skeletonFn: curveDef.skeletonFn
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
function createEngine(curveDef, trailLength = 120) {
|
|
70
70
|
if (!Number.isFinite(trailLength) || trailLength <= 0) {
|
|
71
71
|
throw new RangeError(
|
|
72
|
-
`[sarmal] trailLength must be a positive finite number, got ${trailLength}
|
|
72
|
+
`[sarmal] trailLength must be a positive finite number, got ${trailLength}`
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
let curve = resolveCurve(curveDef);
|
|
@@ -110,7 +110,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
110
110
|
actualTime += deltaTime;
|
|
111
111
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
112
112
|
const a = curve.fn(t, actualTime, EMPTY_PARAMS);
|
|
113
|
-
const tB = _morphStrategy === "normalized" ?
|
|
113
|
+
const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
|
|
114
114
|
const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);
|
|
115
115
|
trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
|
|
116
116
|
} else {
|
|
@@ -137,14 +137,14 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
137
137
|
trail.clear();
|
|
138
138
|
},
|
|
139
139
|
jump(newT, { clearTrail = false } = {}) {
|
|
140
|
-
t = (
|
|
140
|
+
t = (newT % curve.period + curve.period) % curve.period;
|
|
141
141
|
if (clearTrail) {
|
|
142
142
|
trail.clear();
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
145
|
seek(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
|
|
146
146
|
const advance = curve.speed * step;
|
|
147
|
-
const target = (
|
|
147
|
+
const target = (targetT % curve.period + curve.period) % curve.period;
|
|
148
148
|
const targetTime = target / curve.speed;
|
|
149
149
|
t = target;
|
|
150
150
|
actualTime = targetTime;
|
|
@@ -153,7 +153,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
153
153
|
const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
|
|
154
154
|
for (let i = count - 1; i >= 0; i--) {
|
|
155
155
|
const sampleT = target - i * advance;
|
|
156
|
-
const wrappedT = (
|
|
156
|
+
const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
|
|
157
157
|
const time = targetTime - i * step;
|
|
158
158
|
const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
|
|
159
159
|
trail.push(point.x, point.y);
|
|
@@ -170,16 +170,13 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
170
170
|
...frozenB,
|
|
171
171
|
fn: (sampleT, time, params) => {
|
|
172
172
|
const a = frozenA.fn(sampleT, time, params);
|
|
173
|
-
const tB =
|
|
174
|
-
frozenStrategy === "normalized"
|
|
175
|
-
? (sampleT / frozenA.period) * frozenB.period
|
|
176
|
-
: sampleT;
|
|
173
|
+
const tB = frozenStrategy === "normalized" ? sampleT / frozenA.period * frozenB.period : sampleT;
|
|
177
174
|
const b = frozenB.fn(tB, time, params);
|
|
178
175
|
return {
|
|
179
176
|
x: a.x + (b.x - a.x) * frozenAlpha,
|
|
180
|
-
y: a.y + (b.y - a.y) * frozenAlpha
|
|
177
|
+
y: a.y + (b.y - a.y) * frozenAlpha
|
|
181
178
|
};
|
|
182
|
-
}
|
|
179
|
+
}
|
|
183
180
|
};
|
|
184
181
|
}
|
|
185
182
|
_morphStrategy = strategy;
|
|
@@ -192,7 +189,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
192
189
|
completeMorph() {
|
|
193
190
|
if (morphCurveB !== null) {
|
|
194
191
|
if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
|
|
195
|
-
t =
|
|
192
|
+
t = t / curve.period * morphCurveB.period;
|
|
196
193
|
}
|
|
197
194
|
curve = morphCurveB;
|
|
198
195
|
}
|
|
@@ -201,28 +198,25 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
201
198
|
},
|
|
202
199
|
getSarmalSkeleton() {
|
|
203
200
|
const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);
|
|
204
|
-
const
|
|
201
|
+
const points2 = new Array(steps);
|
|
205
202
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
206
203
|
for (let i = 0; i < steps; i++) {
|
|
207
|
-
const sampleT =
|
|
204
|
+
const sampleT = i / (steps - 1) * curve.period;
|
|
208
205
|
const a = sampleSkeleton(curve, sampleT);
|
|
209
|
-
const tB =
|
|
210
|
-
_morphStrategy === "normalized"
|
|
211
|
-
? (sampleT / curve.period) * morphCurveB.period
|
|
212
|
-
: sampleT;
|
|
206
|
+
const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
|
|
213
207
|
const b = sampleSkeleton(morphCurveB, tB);
|
|
214
|
-
|
|
208
|
+
points2[i] = {
|
|
215
209
|
x: a.x + (b.x - a.x) * _morphAlpha,
|
|
216
|
-
y: a.y + (b.y - a.y) * _morphAlpha
|
|
210
|
+
y: a.y + (b.y - a.y) * _morphAlpha
|
|
217
211
|
};
|
|
218
212
|
}
|
|
219
|
-
return
|
|
213
|
+
return points2;
|
|
220
214
|
}
|
|
221
215
|
for (let i = 0; i < steps; i++) {
|
|
222
|
-
const sampleT =
|
|
223
|
-
|
|
216
|
+
const sampleT = i / (steps - 1) * curve.period;
|
|
217
|
+
points2[i] = sampleSkeleton(curve, sampleT);
|
|
224
218
|
}
|
|
225
|
-
return
|
|
219
|
+
return points2;
|
|
226
220
|
},
|
|
227
221
|
setSpeed(speed) {
|
|
228
222
|
if (!Number.isFinite(speed)) {
|
|
@@ -261,7 +255,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
261
255
|
_speedTransition.reject(new Error("Speed transition cancelled"));
|
|
262
256
|
_speedTransition = null;
|
|
263
257
|
}
|
|
264
|
-
}
|
|
258
|
+
}
|
|
265
259
|
};
|
|
266
260
|
}
|
|
267
261
|
|
|
@@ -300,15 +294,7 @@ function computeNormal(trail, i) {
|
|
|
300
294
|
const tangent = computeTangent(trail, i);
|
|
301
295
|
return { x: -tangent.y, y: tangent.x };
|
|
302
296
|
}
|
|
303
|
-
function computeTrailQuad(
|
|
304
|
-
trail,
|
|
305
|
-
i,
|
|
306
|
-
trailCount,
|
|
307
|
-
toX,
|
|
308
|
-
toY,
|
|
309
|
-
minWidth = TRAIL_MIN_WIDTH,
|
|
310
|
-
maxWidth = TRAIL_MAX_WIDTH,
|
|
311
|
-
) {
|
|
297
|
+
function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_WIDTH, maxWidth = TRAIL_MAX_WIDTH) {
|
|
312
298
|
const progress = i / (trailCount - 1);
|
|
313
299
|
const nextProgress = (i + 1) / (trailCount - 1);
|
|
314
300
|
const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
|
|
@@ -332,16 +318,13 @@ function computeTrailQuad(
|
|
|
332
318
|
r1x: nx - n1.x * w1,
|
|
333
319
|
r1y: ny - n1.y * w1,
|
|
334
320
|
opacity,
|
|
335
|
-
progress
|
|
321
|
+
progress
|
|
336
322
|
};
|
|
337
323
|
}
|
|
338
|
-
function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
324
|
+
function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
|
|
339
325
|
if (pts.length === 0) return null;
|
|
340
326
|
const first = pts[0];
|
|
341
|
-
let minX = first.x,
|
|
342
|
-
maxX = first.x,
|
|
343
|
-
minY = first.y,
|
|
344
|
-
maxY = first.y;
|
|
327
|
+
let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
|
|
345
328
|
for (const p of pts) {
|
|
346
329
|
if (p.x < minX) {
|
|
347
330
|
minX = p.x;
|
|
@@ -360,23 +343,23 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
|
360
343
|
const h = maxY - minY;
|
|
361
344
|
if (w === 0 && h === 0) {
|
|
362
345
|
throw new Error(
|
|
363
|
-
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
346
|
+
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
364
347
|
);
|
|
365
348
|
}
|
|
366
349
|
const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
|
|
367
350
|
const scaleYProportional = logicalHeight / (h * (1 + FIT_PADDING * 2));
|
|
368
|
-
const scaleXMinPadding = (logicalWidth -
|
|
369
|
-
const scaleYMinPadding = (logicalHeight -
|
|
351
|
+
const scaleXMinPadding = (logicalWidth - minPaddingPx * 2) / w;
|
|
352
|
+
const scaleYMinPadding = (logicalHeight - minPaddingPx * 2) / h;
|
|
370
353
|
const scale = Math.min(
|
|
371
354
|
scaleXProportional,
|
|
372
355
|
scaleYProportional,
|
|
373
356
|
scaleXMinPadding,
|
|
374
|
-
scaleYMinPadding
|
|
357
|
+
scaleYMinPadding
|
|
375
358
|
);
|
|
376
359
|
return {
|
|
377
360
|
scale,
|
|
378
361
|
offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
|
|
379
|
-
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
362
|
+
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
380
363
|
};
|
|
381
364
|
}
|
|
382
365
|
function enginePassthroughs(engine) {
|
|
@@ -387,6 +370,7 @@ function enginePassthroughs(engine) {
|
|
|
387
370
|
getSpeed: engine.getSpeed,
|
|
388
371
|
resetSpeed: engine.resetSpeed,
|
|
389
372
|
setSpeedOver: engine.setSpeedOver,
|
|
373
|
+
getSarmalSkeleton: engine.getSarmalSkeleton
|
|
390
374
|
};
|
|
391
375
|
}
|
|
392
376
|
var palettes = {
|
|
@@ -395,16 +379,16 @@ var palettes = {
|
|
|
395
379
|
ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
|
|
396
380
|
ice: ["#1e3a8a", "#67e8f9"],
|
|
397
381
|
fire: ["#7f1d1d", "#fbbf24"],
|
|
398
|
-
forest: ["#14532d", "#86efac"]
|
|
382
|
+
forest: ["#14532d", "#86efac"]
|
|
399
383
|
};
|
|
400
384
|
function hexToRgb(hex) {
|
|
401
385
|
const n = parseInt(hex.slice(1), 16);
|
|
402
|
-
return { r: n >> 16, g:
|
|
386
|
+
return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
|
|
403
387
|
}
|
|
404
388
|
var lerpRgb = (a, b, t) => ({
|
|
405
389
|
r: Math.round(a.r + (b.r - a.r) * t),
|
|
406
390
|
g: Math.round(a.g + (b.g - a.g) * t),
|
|
407
|
-
b: Math.round(a.b + (b.b - a.b) * t)
|
|
391
|
+
b: Math.round(a.b + (b.b - a.b) * t)
|
|
408
392
|
});
|
|
409
393
|
function getPaletteColor(palette, position, timeOffset = 0) {
|
|
410
394
|
if (palette.length === 0) {
|
|
@@ -413,7 +397,7 @@ function getPaletteColor(palette, position, timeOffset = 0) {
|
|
|
413
397
|
if (palette.length === 1) {
|
|
414
398
|
return hexToRgb(palette[0]);
|
|
415
399
|
}
|
|
416
|
-
const cyclePos = ((
|
|
400
|
+
const cyclePos = ((position + timeOffset) % 1 + 1) % 1;
|
|
417
401
|
const scaled = cyclePos * palette.length;
|
|
418
402
|
const idx = Math.floor(scaled);
|
|
419
403
|
const t = scaled - idx;
|
|
@@ -428,7 +412,7 @@ var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
428
412
|
"headColor",
|
|
429
413
|
"skeletonColor",
|
|
430
414
|
"trailStyle",
|
|
431
|
-
"headRadius"
|
|
415
|
+
"headRadius"
|
|
432
416
|
]);
|
|
433
417
|
function validateRenderOptions(partial) {
|
|
434
418
|
for (const key of Object.keys(partial)) {
|
|
@@ -456,7 +440,7 @@ function assertTrailColor(value) {
|
|
|
456
440
|
if (typeof value === "string") {
|
|
457
441
|
if (!HEX_COLOR_RE.test(value)) {
|
|
458
442
|
throw new TypeError(
|
|
459
|
-
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"
|
|
443
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`
|
|
460
444
|
);
|
|
461
445
|
}
|
|
462
446
|
return;
|
|
@@ -464,21 +448,21 @@ function assertTrailColor(value) {
|
|
|
464
448
|
if (Array.isArray(value)) {
|
|
465
449
|
if (value.length < 2) {
|
|
466
450
|
throw new RangeError(
|
|
467
|
-
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}
|
|
451
|
+
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`
|
|
468
452
|
);
|
|
469
453
|
}
|
|
470
454
|
for (let i = 0; i < value.length; i++) {
|
|
471
455
|
const entry = value[i];
|
|
472
456
|
if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
|
|
473
457
|
throw new TypeError(
|
|
474
|
-
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}
|
|
458
|
+
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`
|
|
475
459
|
);
|
|
476
460
|
}
|
|
477
461
|
}
|
|
478
462
|
return;
|
|
479
463
|
}
|
|
480
464
|
throw new TypeError(
|
|
481
|
-
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}
|
|
465
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`
|
|
482
466
|
);
|
|
483
467
|
}
|
|
484
468
|
function assertHeadColor(value) {
|
|
@@ -487,7 +471,7 @@ function assertHeadColor(value) {
|
|
|
487
471
|
}
|
|
488
472
|
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
489
473
|
throw new TypeError(
|
|
490
|
-
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}
|
|
474
|
+
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`
|
|
491
475
|
);
|
|
492
476
|
}
|
|
493
477
|
}
|
|
@@ -497,26 +481,26 @@ function assertSkeletonColor(value) {
|
|
|
497
481
|
}
|
|
498
482
|
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
499
483
|
throw new TypeError(
|
|
500
|
-
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}
|
|
484
|
+
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`
|
|
501
485
|
);
|
|
502
486
|
}
|
|
503
487
|
}
|
|
504
488
|
function assertTrailStyle(value) {
|
|
505
489
|
if (!TRAIL_STYLES.includes(value)) {
|
|
506
490
|
throw new RangeError(
|
|
507
|
-
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}
|
|
491
|
+
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`
|
|
508
492
|
);
|
|
509
493
|
}
|
|
510
494
|
}
|
|
511
495
|
function assertHeadRadius(value) {
|
|
512
496
|
if (typeof value !== "number") {
|
|
513
497
|
throw new TypeError(
|
|
514
|
-
`[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}
|
|
498
|
+
`[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`
|
|
515
499
|
);
|
|
516
500
|
}
|
|
517
501
|
if (!Number.isFinite(value) || value <= 0) {
|
|
518
502
|
throw new TypeError(
|
|
519
|
-
`[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}
|
|
503
|
+
`[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`
|
|
520
504
|
);
|
|
521
505
|
}
|
|
522
506
|
}
|
|
@@ -538,13 +522,13 @@ function resolveHeadColor(trailColor, trailStyle) {
|
|
|
538
522
|
function warnIfTrailColorMismatch(trailColor, trailStyle) {
|
|
539
523
|
if (trailStyle === "default" && Array.isArray(trailColor)) {
|
|
540
524
|
console.warn(
|
|
541
|
-
'[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.'
|
|
525
|
+
'[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.'
|
|
542
526
|
);
|
|
543
527
|
return;
|
|
544
528
|
}
|
|
545
529
|
if (trailStyle !== "default" && typeof trailColor === "string") {
|
|
546
530
|
console.warn(
|
|
547
|
-
`[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
|
|
531
|
+
`[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.`
|
|
548
532
|
);
|
|
549
533
|
}
|
|
550
534
|
}
|
|
@@ -554,7 +538,7 @@ var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160)
|
|
|
554
538
|
var WHITE_HEX = "#ffffff";
|
|
555
539
|
function hexToRgbComponents(hex) {
|
|
556
540
|
const n = parseInt(hex.slice(1), 16);
|
|
557
|
-
return `${n >> 16},${
|
|
541
|
+
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
558
542
|
}
|
|
559
543
|
function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
|
|
560
544
|
target.style.width = `${logicalWidth}px`;
|
|
@@ -598,6 +582,7 @@ function createRenderer(options) {
|
|
|
598
582
|
let offsetY = 0;
|
|
599
583
|
let animationId = null;
|
|
600
584
|
let lastTime = 0;
|
|
585
|
+
let pausedByVisibility = false;
|
|
601
586
|
let morphResolve = null;
|
|
602
587
|
let morphReject = null;
|
|
603
588
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
@@ -680,7 +665,7 @@ function createRenderer(options) {
|
|
|
680
665
|
i,
|
|
681
666
|
trailCount,
|
|
682
667
|
toX,
|
|
683
|
-
toY
|
|
668
|
+
toY
|
|
684
669
|
);
|
|
685
670
|
if (trailStyle === "default") {
|
|
686
671
|
ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
|
|
@@ -791,6 +776,7 @@ function createRenderer(options) {
|
|
|
791
776
|
cancelAnimationFrame(animationId);
|
|
792
777
|
animationId = null;
|
|
793
778
|
}
|
|
779
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
794
780
|
if (morphReject !== null) {
|
|
795
781
|
morphReject(new Error("Instance destroyed during morph"));
|
|
796
782
|
morphResolve = null;
|
|
@@ -844,10 +830,30 @@ function createRenderer(options) {
|
|
|
844
830
|
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
845
831
|
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
846
832
|
}
|
|
847
|
-
}
|
|
833
|
+
}
|
|
848
834
|
};
|
|
849
|
-
|
|
835
|
+
const pauseOnHidden = options.pauseOnHidden !== false;
|
|
836
|
+
function handleVisibilityChange() {
|
|
837
|
+
if (document.hidden) {
|
|
838
|
+
if (animationId !== null) {
|
|
839
|
+
instance.pause();
|
|
840
|
+
pausedByVisibility = true;
|
|
841
|
+
}
|
|
842
|
+
} else {
|
|
843
|
+
if (pausedByVisibility) {
|
|
844
|
+
pausedByVisibility = false;
|
|
845
|
+
instance.play();
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (pauseOnHidden) {
|
|
850
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
851
|
+
}
|
|
852
|
+
const actuallyAutoStart = shouldAutoStart && !(pauseOnHidden && document.hidden);
|
|
853
|
+
if (actuallyAutoStart) {
|
|
850
854
|
instance.play();
|
|
855
|
+
} else if (shouldAutoStart) {
|
|
856
|
+
pausedByVisibility = true;
|
|
851
857
|
}
|
|
852
858
|
return instance;
|
|
853
859
|
}
|
|
@@ -874,7 +880,7 @@ function sampleCurveSkeleton(curveDef) {
|
|
|
874
880
|
const samples = Math.ceil(period * 50);
|
|
875
881
|
const pts = Array.from({ length: samples });
|
|
876
882
|
for (let i = 0; i < samples; i++) {
|
|
877
|
-
const t =
|
|
883
|
+
const t = i / (samples - 1) * period;
|
|
878
884
|
pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS2);
|
|
879
885
|
}
|
|
880
886
|
return pts;
|
|
@@ -887,7 +893,7 @@ function createSVGRenderer(options) {
|
|
|
887
893
|
const poolSize = engine.trailLength;
|
|
888
894
|
if (poolSize > HIGH_TRAIL_LENGTH_THRESHOLD) {
|
|
889
895
|
console.warn(
|
|
890
|
-
`[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails
|
|
896
|
+
`[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails.`
|
|
891
897
|
);
|
|
892
898
|
}
|
|
893
899
|
let trailStyle = options.trailStyle ?? "default";
|
|
@@ -906,9 +912,9 @@ function createSVGRenderer(options) {
|
|
|
906
912
|
return rect.width && rect.height ? Math.min(rect.width, rect.height) : 200;
|
|
907
913
|
}
|
|
908
914
|
const containerPx = getContainerPixelSize();
|
|
909
|
-
const svgTrailMinWidth =
|
|
910
|
-
const svgTrailMaxWidth =
|
|
911
|
-
const svgSkeletonStrokeWidth = String(
|
|
915
|
+
const svgTrailMinWidth = TRAIL_MIN_WIDTH * viewSize / containerPx;
|
|
916
|
+
const svgTrailMaxWidth = TRAIL_MAX_WIDTH * viewSize / containerPx;
|
|
917
|
+
const svgSkeletonStrokeWidth = String(SKELETON_STROKE_WIDTH_PX * viewSize / containerPx);
|
|
912
918
|
headRadius = options.headRadius ?? SVG_DEFAULT_HEAD_RADIUS;
|
|
913
919
|
container.setAttribute("viewBox", `0 0 ${viewSize} ${viewSize}`);
|
|
914
920
|
container.setAttribute("role", "img");
|
|
@@ -996,7 +1002,7 @@ function createSVGRenderer(options) {
|
|
|
996
1002
|
px,
|
|
997
1003
|
py,
|
|
998
1004
|
svgTrailMinWidth,
|
|
999
|
-
svgTrailMaxWidth
|
|
1005
|
+
svgTrailMaxWidth
|
|
1000
1006
|
);
|
|
1001
1007
|
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`;
|
|
1002
1008
|
trailPaths[i].setAttribute("d", d);
|
|
@@ -1023,8 +1029,8 @@ function createSVGRenderer(options) {
|
|
|
1023
1029
|
}
|
|
1024
1030
|
let animationId = null;
|
|
1025
1031
|
let lastTime = 0;
|
|
1026
|
-
|
|
1027
|
-
|
|
1032
|
+
let pausedByVisibility = false;
|
|
1033
|
+
const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1028
1034
|
let morphResolve = null;
|
|
1029
1035
|
let morphReject = null;
|
|
1030
1036
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
@@ -1042,7 +1048,7 @@ function createSVGRenderer(options) {
|
|
|
1042
1048
|
skeletonPathA.setAttribute("visibility", "visible");
|
|
1043
1049
|
skeletonPathA.setAttribute(
|
|
1044
1050
|
"stroke-opacity",
|
|
1045
|
-
String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
|
|
1051
|
+
String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
|
|
1046
1052
|
);
|
|
1047
1053
|
}
|
|
1048
1054
|
if (morphPathBBuilt) {
|
|
@@ -1114,6 +1120,7 @@ function createSVGRenderer(options) {
|
|
|
1114
1120
|
cancelAnimationFrame(animationId);
|
|
1115
1121
|
animationId = null;
|
|
1116
1122
|
}
|
|
1123
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1117
1124
|
if (morphReject !== null) {
|
|
1118
1125
|
morphReject(new Error("Instance destroyed during morph"));
|
|
1119
1126
|
morphResolve = null;
|
|
@@ -1195,10 +1202,30 @@ function createSVGRenderer(options) {
|
|
|
1195
1202
|
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
1196
1203
|
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
1197
1204
|
}
|
|
1198
|
-
}
|
|
1205
|
+
}
|
|
1199
1206
|
};
|
|
1200
|
-
|
|
1207
|
+
const pauseOnHidden = options.pauseOnHidden !== false;
|
|
1208
|
+
function handleVisibilityChange() {
|
|
1209
|
+
if (document.hidden) {
|
|
1210
|
+
if (animationId !== null) {
|
|
1211
|
+
instance.pause();
|
|
1212
|
+
pausedByVisibility = true;
|
|
1213
|
+
}
|
|
1214
|
+
} else {
|
|
1215
|
+
if (pausedByVisibility) {
|
|
1216
|
+
pausedByVisibility = false;
|
|
1217
|
+
instance.play();
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
if (pauseOnHidden) {
|
|
1222
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
1223
|
+
}
|
|
1224
|
+
const actuallyAutoStart = shouldAutoStart && !(pauseOnHidden && document.hidden);
|
|
1225
|
+
if (actuallyAutoStart) {
|
|
1201
1226
|
instance.play();
|
|
1227
|
+
} else if (shouldAutoStart) {
|
|
1228
|
+
pausedByVisibility = true;
|
|
1202
1229
|
}
|
|
1203
1230
|
return instance;
|
|
1204
1231
|
}
|
|
@@ -1208,254 +1235,309 @@ function createSarmalSVG(container, curveDef, options) {
|
|
|
1208
1235
|
return createSVGRenderer({ container, engine, ...rendererOpts });
|
|
1209
1236
|
}
|
|
1210
1237
|
|
|
1211
|
-
// src/
|
|
1212
|
-
var
|
|
1213
|
-
function
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
const
|
|
1238
|
+
// src/catmull-rom.ts
|
|
1239
|
+
var PERIOD = 2 * Math.PI;
|
|
1240
|
+
function catmullRom1D(p0, p1, p2, p3, u) {
|
|
1241
|
+
const u2 = u * u;
|
|
1242
|
+
const u3 = u2 * u;
|
|
1243
|
+
return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
|
|
1244
|
+
}
|
|
1245
|
+
function evaluateCatmullRom(points2, t) {
|
|
1246
|
+
const N = points2.length;
|
|
1247
|
+
if (N === 0) {
|
|
1248
|
+
return { x: 0, y: 0 };
|
|
1249
|
+
}
|
|
1250
|
+
if (N === 1) {
|
|
1251
|
+
return { x: points2[0][0], y: points2[0][1] };
|
|
1252
|
+
}
|
|
1253
|
+
t = (t % PERIOD + PERIOD) % PERIOD;
|
|
1254
|
+
const segmentSize = PERIOD / N;
|
|
1255
|
+
let i = Math.floor(t / segmentSize);
|
|
1256
|
+
if (i >= N) {
|
|
1257
|
+
i = N - 1;
|
|
1258
|
+
}
|
|
1259
|
+
let u = (t - i * segmentSize) / segmentSize;
|
|
1260
|
+
u = Math.max(0, Math.min(1, u));
|
|
1261
|
+
const p0 = points2[(i - 1 + N) % N];
|
|
1262
|
+
const p1 = points2[i];
|
|
1263
|
+
const p2 = points2[(i + 1) % N];
|
|
1264
|
+
const p3 = points2[(i + 2) % N];
|
|
1220
1265
|
return {
|
|
1221
|
-
x: (
|
|
1222
|
-
y: (
|
|
1266
|
+
x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
|
|
1267
|
+
y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
function drawCurve(points2, opts) {
|
|
1271
|
+
if (points2.length < 3) {
|
|
1272
|
+
throw new Error(`drawCurve requires at least 3 points, received ${points2.length}.`);
|
|
1273
|
+
}
|
|
1274
|
+
const first = points2[0];
|
|
1275
|
+
if (points2.every((p) => p[0] === first[0] && p[1] === first[1])) {
|
|
1276
|
+
console.warn(
|
|
1277
|
+
"[sarmal].drawCurve: all control points are identical. The curve will be a single point."
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
const maxAbs = points2.reduce((m, p) => Math.max(m, Math.abs(p[0]), Math.abs(p[1])), 0);
|
|
1281
|
+
if (maxAbs > 2) {
|
|
1282
|
+
console.warn(
|
|
1283
|
+
`[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
const pts = points2.map(([x, y]) => [x, y]);
|
|
1287
|
+
return {
|
|
1288
|
+
name: opts?.name ?? "drawn",
|
|
1289
|
+
fn: (t) => evaluateCatmullRom(pts, t),
|
|
1290
|
+
period: PERIOD,
|
|
1291
|
+
kind: "drawn"
|
|
1223
1292
|
};
|
|
1224
1293
|
}
|
|
1294
|
+
|
|
1295
|
+
// src/curves/artemis2.ts
|
|
1296
|
+
var points = [
|
|
1297
|
+
[-0.44, -0.45],
|
|
1298
|
+
[-0.53, -0.77],
|
|
1299
|
+
[-0.82, -0.66],
|
|
1300
|
+
[-0.82, -0.18],
|
|
1301
|
+
[-0.25, -0.04],
|
|
1302
|
+
[0.16, -0.49],
|
|
1303
|
+
[-0.03, -0.87],
|
|
1304
|
+
[-0.68, -0.94],
|
|
1305
|
+
[-0.95, -0.61],
|
|
1306
|
+
[-0.87, -0],
|
|
1307
|
+
[-0.34, 0.21],
|
|
1308
|
+
[0.27, -0.04],
|
|
1309
|
+
[0.87, 0.06],
|
|
1310
|
+
[0.87, 0.57],
|
|
1311
|
+
[0.32, 0.66],
|
|
1312
|
+
[-0.21, -0.43],
|
|
1313
|
+
[-0.43, -0.81],
|
|
1314
|
+
[-0.69, -0.84],
|
|
1315
|
+
[-0.87, -0.66],
|
|
1316
|
+
[-0.9, -0.47],
|
|
1317
|
+
[-0.76, -0.35]
|
|
1318
|
+
];
|
|
1225
1319
|
var artemis2 = {
|
|
1226
|
-
name: "Artemis II",
|
|
1227
|
-
|
|
1228
|
-
period: TWO_PI2,
|
|
1229
|
-
speed: 0.7,
|
|
1320
|
+
...drawCurve(points, { name: "Artemis II" }),
|
|
1321
|
+
speed: 0.7
|
|
1230
1322
|
};
|
|
1231
1323
|
|
|
1232
1324
|
// src/curves/astroid.ts
|
|
1233
|
-
var
|
|
1325
|
+
var TWO_PI2 = Math.PI * 2;
|
|
1234
1326
|
function astroidFn(t, _time, _params) {
|
|
1235
1327
|
const c = Math.cos(t);
|
|
1236
1328
|
const s = Math.sin(t);
|
|
1237
1329
|
return {
|
|
1238
1330
|
x: c * c * c,
|
|
1239
|
-
y: s * s * s
|
|
1331
|
+
y: s * s * s
|
|
1240
1332
|
};
|
|
1241
1333
|
}
|
|
1242
1334
|
var astroid = {
|
|
1243
1335
|
name: "Astroid",
|
|
1244
1336
|
fn: astroidFn,
|
|
1245
|
-
period:
|
|
1246
|
-
speed: 1.1
|
|
1337
|
+
period: TWO_PI2,
|
|
1338
|
+
speed: 1.1
|
|
1247
1339
|
};
|
|
1248
1340
|
|
|
1249
1341
|
// src/curves/deltoid.ts
|
|
1250
|
-
var
|
|
1342
|
+
var TWO_PI3 = Math.PI * 2;
|
|
1251
1343
|
function deltoidFn(t, _time, _params) {
|
|
1252
1344
|
return {
|
|
1253
1345
|
x: 2 * Math.cos(t) + Math.cos(2 * t),
|
|
1254
|
-
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
1346
|
+
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
1255
1347
|
};
|
|
1256
1348
|
}
|
|
1257
1349
|
var deltoid = {
|
|
1258
1350
|
name: "Deltoid",
|
|
1259
1351
|
fn: deltoidFn,
|
|
1260
|
-
period:
|
|
1261
|
-
speed: 0.9
|
|
1352
|
+
period: TWO_PI3,
|
|
1353
|
+
speed: 0.9
|
|
1262
1354
|
};
|
|
1263
1355
|
|
|
1264
1356
|
// src/curves/epicycloid3.ts
|
|
1265
|
-
var
|
|
1357
|
+
var TWO_PI4 = Math.PI * 2;
|
|
1266
1358
|
function epicycloid3Fn(t, _time, _params) {
|
|
1267
1359
|
return {
|
|
1268
1360
|
x: 4 * Math.cos(t) - Math.cos(4 * t),
|
|
1269
|
-
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
1361
|
+
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
1270
1362
|
};
|
|
1271
1363
|
}
|
|
1272
1364
|
var epicycloid3 = {
|
|
1273
1365
|
name: "Epicycloid (n=3)",
|
|
1274
1366
|
fn: epicycloid3Fn,
|
|
1275
|
-
period:
|
|
1276
|
-
speed: 0.75
|
|
1367
|
+
period: TWO_PI4,
|
|
1368
|
+
speed: 0.75
|
|
1277
1369
|
};
|
|
1278
1370
|
|
|
1279
1371
|
// src/curves/epitrochoid7.ts
|
|
1280
|
-
var
|
|
1372
|
+
var TWO_PI5 = Math.PI * 2;
|
|
1281
1373
|
function epitrochoid7Fn(t, _time, _params) {
|
|
1282
1374
|
const d = 1 + 0.55 * Math.sin(t * 0.5);
|
|
1283
1375
|
return {
|
|
1284
1376
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
1285
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1377
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1286
1378
|
};
|
|
1287
1379
|
}
|
|
1288
1380
|
function epitrochoid7SkeletonFn(t) {
|
|
1289
1381
|
const d = 1.275;
|
|
1290
1382
|
return {
|
|
1291
1383
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
1292
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1384
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
1293
1385
|
};
|
|
1294
1386
|
}
|
|
1295
1387
|
var epitrochoid7 = {
|
|
1296
1388
|
name: "Epitrochoid",
|
|
1297
1389
|
fn: epitrochoid7Fn,
|
|
1298
|
-
period:
|
|
1390
|
+
period: TWO_PI5,
|
|
1299
1391
|
speed: 1.4,
|
|
1300
|
-
skeletonFn: epitrochoid7SkeletonFn
|
|
1392
|
+
skeletonFn: epitrochoid7SkeletonFn
|
|
1301
1393
|
};
|
|
1302
1394
|
|
|
1303
1395
|
// src/curves/lissajous32.ts
|
|
1304
|
-
var
|
|
1396
|
+
var TWO_PI6 = Math.PI * 2;
|
|
1305
1397
|
function lissajous32Fn(t, time, _params) {
|
|
1306
1398
|
const phi = time * 0.45;
|
|
1307
1399
|
return {
|
|
1308
1400
|
x: Math.sin(3 * t + phi),
|
|
1309
|
-
y: Math.sin(2 * t)
|
|
1401
|
+
y: Math.sin(2 * t)
|
|
1310
1402
|
};
|
|
1311
1403
|
}
|
|
1312
1404
|
var lissajous32 = {
|
|
1313
1405
|
name: "Lissajous 3:2",
|
|
1314
1406
|
fn: lissajous32Fn,
|
|
1315
|
-
period:
|
|
1407
|
+
period: TWO_PI6,
|
|
1316
1408
|
speed: 2,
|
|
1317
|
-
skeleton: "live"
|
|
1409
|
+
skeleton: "live"
|
|
1318
1410
|
};
|
|
1319
1411
|
|
|
1320
1412
|
// src/curves/lissajous43.ts
|
|
1321
|
-
var
|
|
1413
|
+
var TWO_PI7 = Math.PI * 2;
|
|
1322
1414
|
function lissajous43Fn(t, time, _params) {
|
|
1323
1415
|
const phi = time * 0.38;
|
|
1324
1416
|
return {
|
|
1325
1417
|
x: Math.sin(4 * t + phi),
|
|
1326
|
-
y: Math.sin(3 * t)
|
|
1418
|
+
y: Math.sin(3 * t)
|
|
1327
1419
|
};
|
|
1328
1420
|
}
|
|
1329
1421
|
var lissajous43 = {
|
|
1330
1422
|
name: "Lissajous 4:3",
|
|
1331
1423
|
fn: lissajous43Fn,
|
|
1332
|
-
period:
|
|
1424
|
+
period: TWO_PI7,
|
|
1333
1425
|
speed: 1.8,
|
|
1334
|
-
skeleton: "live"
|
|
1426
|
+
skeleton: "live"
|
|
1335
1427
|
};
|
|
1336
1428
|
|
|
1337
1429
|
// src/curves/lame.ts
|
|
1338
|
-
var
|
|
1430
|
+
var TWO_PI8 = Math.PI * 2;
|
|
1339
1431
|
function lameFn(t, time, _params) {
|
|
1340
1432
|
const p = 1.75 + 1.25 * Math.sin(time * 0.48);
|
|
1341
|
-
const c = Math.cos(t),
|
|
1342
|
-
s = Math.sin(t);
|
|
1433
|
+
const c = Math.cos(t), s = Math.sin(t);
|
|
1343
1434
|
return {
|
|
1344
1435
|
x: Math.sign(c) * Math.pow(Math.abs(c), p),
|
|
1345
|
-
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
1436
|
+
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
1346
1437
|
};
|
|
1347
1438
|
}
|
|
1348
1439
|
var lame = {
|
|
1349
1440
|
name: "Lam\xE9 Curve",
|
|
1350
1441
|
fn: lameFn,
|
|
1351
|
-
period:
|
|
1442
|
+
period: TWO_PI8,
|
|
1352
1443
|
speed: 1,
|
|
1353
|
-
skeleton: "live"
|
|
1444
|
+
skeleton: "live"
|
|
1354
1445
|
};
|
|
1355
1446
|
|
|
1356
1447
|
// src/curves/rose3.ts
|
|
1357
|
-
var
|
|
1448
|
+
var TWO_PI9 = Math.PI * 2;
|
|
1358
1449
|
function rose3Fn(t, _time, _params) {
|
|
1359
1450
|
const r = Math.cos(3 * t);
|
|
1360
1451
|
return {
|
|
1361
1452
|
x: r * Math.cos(t),
|
|
1362
|
-
y: r * Math.sin(t)
|
|
1453
|
+
y: r * Math.sin(t)
|
|
1363
1454
|
};
|
|
1364
1455
|
}
|
|
1365
1456
|
var rose3 = {
|
|
1366
1457
|
name: "Rose (n=3)",
|
|
1367
1458
|
fn: rose3Fn,
|
|
1368
|
-
period:
|
|
1369
|
-
speed: 1.15
|
|
1459
|
+
period: TWO_PI9,
|
|
1460
|
+
speed: 1.15
|
|
1370
1461
|
};
|
|
1371
1462
|
|
|
1372
1463
|
// src/curves/rose5.ts
|
|
1373
|
-
var
|
|
1464
|
+
var TWO_PI10 = Math.PI * 2;
|
|
1374
1465
|
function rose5Fn(t, _time, _params) {
|
|
1375
1466
|
const r = Math.cos(5 * t);
|
|
1376
1467
|
return {
|
|
1377
1468
|
x: r * Math.cos(t),
|
|
1378
|
-
y: r * Math.sin(t)
|
|
1469
|
+
y: r * Math.sin(t)
|
|
1379
1470
|
};
|
|
1380
1471
|
}
|
|
1381
1472
|
var rose5 = {
|
|
1382
1473
|
name: "Rose (n=5)",
|
|
1383
1474
|
fn: rose5Fn,
|
|
1384
|
-
period:
|
|
1385
|
-
speed: 1
|
|
1475
|
+
period: TWO_PI10,
|
|
1476
|
+
speed: 1
|
|
1386
1477
|
};
|
|
1387
1478
|
|
|
1388
1479
|
// src/curves/rose52.ts
|
|
1389
1480
|
var FOUR_PI = Math.PI * 4;
|
|
1390
1481
|
function rose52Fn(t, _time, _params) {
|
|
1391
|
-
const r = Math.cos(
|
|
1482
|
+
const r = Math.cos(5 / 2 * t);
|
|
1392
1483
|
return {
|
|
1393
1484
|
x: r * Math.cos(t),
|
|
1394
|
-
y: r * Math.sin(t)
|
|
1485
|
+
y: r * Math.sin(t)
|
|
1395
1486
|
};
|
|
1396
1487
|
}
|
|
1397
1488
|
var rose52 = {
|
|
1398
1489
|
name: "Rose (n=5/2)",
|
|
1399
1490
|
fn: rose52Fn,
|
|
1400
1491
|
period: FOUR_PI,
|
|
1401
|
-
speed: 0.8
|
|
1492
|
+
speed: 0.8
|
|
1402
1493
|
};
|
|
1403
1494
|
|
|
1404
1495
|
// src/curves/star.ts
|
|
1405
|
-
var
|
|
1496
|
+
var TWO_PI11 = Math.PI * 2;
|
|
1406
1497
|
function starFn(t, _time, _params) {
|
|
1407
|
-
const r =
|
|
1408
|
-
Math.abs(Math.cos((5 / 2) * t)) +
|
|
1409
|
-
0.35 * Math.abs(Math.cos((15 / 2) * t)) +
|
|
1410
|
-
0.15 * Math.abs(Math.cos((25 / 2) * t));
|
|
1498
|
+
const r = Math.abs(Math.cos(5 / 2 * t)) + 0.35 * Math.abs(Math.cos(15 / 2 * t)) + 0.15 * Math.abs(Math.cos(25 / 2 * t));
|
|
1411
1499
|
return {
|
|
1412
1500
|
x: r * Math.cos(t),
|
|
1413
|
-
y: r * Math.sin(t)
|
|
1501
|
+
y: r * Math.sin(t)
|
|
1414
1502
|
};
|
|
1415
1503
|
}
|
|
1416
1504
|
var star = {
|
|
1417
1505
|
name: "Star",
|
|
1418
1506
|
fn: starFn,
|
|
1419
|
-
period:
|
|
1420
|
-
speed: 1
|
|
1507
|
+
period: TWO_PI11,
|
|
1508
|
+
speed: 1
|
|
1421
1509
|
};
|
|
1422
1510
|
|
|
1423
1511
|
// src/curves/star4.ts
|
|
1424
|
-
var
|
|
1512
|
+
var TWO_PI12 = Math.PI * 2;
|
|
1425
1513
|
function star4Fn(t, _time, _params) {
|
|
1426
|
-
const r =
|
|
1427
|
-
Math.abs(Math.cos(2 * t)) +
|
|
1428
|
-
0.35 * Math.abs(Math.cos(6 * t)) +
|
|
1429
|
-
0.15 * Math.abs(Math.cos(10 * t));
|
|
1514
|
+
const r = Math.abs(Math.cos(2 * t)) + 0.35 * Math.abs(Math.cos(6 * t)) + 0.15 * Math.abs(Math.cos(10 * t));
|
|
1430
1515
|
return {
|
|
1431
1516
|
x: r * Math.cos(t),
|
|
1432
|
-
y: r * Math.sin(t)
|
|
1517
|
+
y: r * Math.sin(t)
|
|
1433
1518
|
};
|
|
1434
1519
|
}
|
|
1435
1520
|
var star4 = {
|
|
1436
1521
|
name: "Star (4-arm)",
|
|
1437
1522
|
fn: star4Fn,
|
|
1438
|
-
period:
|
|
1439
|
-
speed: 1
|
|
1523
|
+
period: TWO_PI12,
|
|
1524
|
+
speed: 1
|
|
1440
1525
|
};
|
|
1441
1526
|
|
|
1442
1527
|
// src/curves/star7.ts
|
|
1443
|
-
var
|
|
1528
|
+
var TWO_PI13 = Math.PI * 2;
|
|
1444
1529
|
function star7Fn(t, _time, _params) {
|
|
1445
|
-
const r =
|
|
1446
|
-
Math.abs(Math.cos((7 / 2) * t)) +
|
|
1447
|
-
0.35 * Math.abs(Math.cos((21 / 2) * t)) +
|
|
1448
|
-
0.15 * Math.abs(Math.cos((35 / 2) * t));
|
|
1530
|
+
const r = Math.abs(Math.cos(7 / 2 * t)) + 0.35 * Math.abs(Math.cos(21 / 2 * t)) + 0.15 * Math.abs(Math.cos(35 / 2 * t));
|
|
1449
1531
|
return {
|
|
1450
1532
|
x: r * Math.cos(t),
|
|
1451
|
-
y: r * Math.sin(t)
|
|
1533
|
+
y: r * Math.sin(t)
|
|
1452
1534
|
};
|
|
1453
1535
|
}
|
|
1454
1536
|
var star7 = {
|
|
1455
1537
|
name: "Star (7-arm)",
|
|
1456
1538
|
fn: star7Fn,
|
|
1457
|
-
period:
|
|
1458
|
-
speed: 1
|
|
1539
|
+
period: TWO_PI13,
|
|
1540
|
+
speed: 1
|
|
1459
1541
|
};
|
|
1460
1542
|
|
|
1461
1543
|
// src/curves/index.ts
|
|
@@ -1473,58 +1555,9 @@ var curves = {
|
|
|
1473
1555
|
lissajous32,
|
|
1474
1556
|
lissajous43,
|
|
1475
1557
|
epicycloid3,
|
|
1476
|
-
lame
|
|
1558
|
+
lame
|
|
1477
1559
|
};
|
|
1478
1560
|
|
|
1479
|
-
// src/catmull-rom.ts
|
|
1480
|
-
var PERIOD = 2 * Math.PI;
|
|
1481
|
-
function catmullRom1D(p0, p1, p2, p3, u) {
|
|
1482
|
-
const u2 = u * u;
|
|
1483
|
-
const u3 = u2 * u;
|
|
1484
|
-
return (
|
|
1485
|
-
0.5 *
|
|
1486
|
-
(2 * p1 +
|
|
1487
|
-
(-p0 + p2) * u +
|
|
1488
|
-
(2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 +
|
|
1489
|
-
(-p0 + 3 * p1 - 3 * p2 + p3) * u3)
|
|
1490
|
-
);
|
|
1491
|
-
}
|
|
1492
|
-
function evaluateCatmullRom(points, t) {
|
|
1493
|
-
const N = points.length;
|
|
1494
|
-
if (N === 0) {
|
|
1495
|
-
return { x: 0, y: 0 };
|
|
1496
|
-
}
|
|
1497
|
-
if (N === 1) {
|
|
1498
|
-
return { x: points[0][0], y: points[0][1] };
|
|
1499
|
-
}
|
|
1500
|
-
t = ((t % PERIOD) + PERIOD) % PERIOD;
|
|
1501
|
-
const segmentSize = PERIOD / N;
|
|
1502
|
-
let i = Math.floor(t / segmentSize);
|
|
1503
|
-
if (i >= N) {
|
|
1504
|
-
i = N - 1;
|
|
1505
|
-
}
|
|
1506
|
-
let u = (t - i * segmentSize) / segmentSize;
|
|
1507
|
-
u = Math.max(0, Math.min(1, u));
|
|
1508
|
-
const p0 = points[(i - 1 + N) % N];
|
|
1509
|
-
const p1 = points[i];
|
|
1510
|
-
const p2 = points[(i + 1) % N];
|
|
1511
|
-
const p3 = points[(i + 2) % N];
|
|
1512
|
-
return {
|
|
1513
|
-
x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
|
|
1514
|
-
y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u),
|
|
1515
|
-
};
|
|
1516
|
-
}
|
|
1517
|
-
function drawCurve(points) {
|
|
1518
|
-
if (points.length < 3) {
|
|
1519
|
-
throw new Error(`drawCurve requires at least 3 points, received ${points.length}.`);
|
|
1520
|
-
}
|
|
1521
|
-
return {
|
|
1522
|
-
name: "custom",
|
|
1523
|
-
fn: (t) => evaluateCatmullRom(points, t),
|
|
1524
|
-
period: PERIOD,
|
|
1525
|
-
};
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
1561
|
// src/index.ts
|
|
1529
1562
|
function createSarmal(canvas, curveDef, options) {
|
|
1530
1563
|
const { trailLength, ...rendererOpts } = options ?? {};
|
|
@@ -1534,6 +1567,7 @@ function createSarmal(canvas, curveDef, options) {
|
|
|
1534
1567
|
|
|
1535
1568
|
exports.artemis2 = artemis2;
|
|
1536
1569
|
exports.astroid = astroid;
|
|
1570
|
+
exports.computeBoundaries = computeBoundaries;
|
|
1537
1571
|
exports.createEngine = createEngine;
|
|
1538
1572
|
exports.createRenderer = createRenderer;
|
|
1539
1573
|
exports.createSVGRenderer = createSVGRenderer;
|
|
@@ -1552,4 +1586,4 @@ exports.palettes = palettes;
|
|
|
1552
1586
|
exports.rose3 = rose3;
|
|
1553
1587
|
exports.rose5 = rose5;
|
|
1554
1588
|
//# sourceMappingURL=index.cjs.map
|
|
1555
|
-
//# sourceMappingURL=index.cjs.map
|
|
1589
|
+
//# sourceMappingURL=index.cjs.map
|