@sarmal/core 0.14.0 → 0.15.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 +239 -115
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.d.cts +1 -2
- package/dist/auto-init.d.ts +1 -2
- package/dist/auto-init.js +238 -114
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.cjs +10 -7
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/artemis2.js +9 -6
- 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 +32 -28
- package/dist/curves/index.d.cts +21 -21
- package/dist/curves/index.d.ts +21 -21
- package/dist/curves/index.js +44 -28
- 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/index.cjs +303 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -23
- package/dist/index.d.ts +73 -23
- package/dist/index.js +320 -123
- package/dist/index.js.map +1 -1
- package/dist/types-BL9HhEmk.d.cts +312 -0
- package/dist/types-BL9HhEmk.d.ts +312 -0
- package/package.json +1 -1
- package/dist/types-BQosOzlf.d.cts +0 -276
- package/dist/types-BQosOzlf.d.ts +0 -276
package/dist/auto-init.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 {
|
|
@@ -132,14 +132,14 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
132
132
|
trail.clear();
|
|
133
133
|
},
|
|
134
134
|
jump(newT, { clearTrail = false } = {}) {
|
|
135
|
-
t = (newT % curve.period + curve.period) % curve.period;
|
|
135
|
+
t = ((newT % curve.period) + curve.period) % curve.period;
|
|
136
136
|
if (clearTrail) {
|
|
137
137
|
trail.clear();
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
seek(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
|
|
141
141
|
const advance = curve.speed * step;
|
|
142
|
-
const target = (targetT % curve.period + curve.period) % curve.period;
|
|
142
|
+
const target = ((targetT % curve.period) + curve.period) % curve.period;
|
|
143
143
|
const targetTime = target / curve.speed;
|
|
144
144
|
t = target;
|
|
145
145
|
actualTime = targetTime;
|
|
@@ -148,7 +148,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
148
148
|
const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
|
|
149
149
|
for (let i = count - 1; i >= 0; i--) {
|
|
150
150
|
const sampleT = target - i * advance;
|
|
151
|
-
const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
|
|
151
|
+
const wrappedT = ((sampleT % curve.period) + curve.period) % curve.period;
|
|
152
152
|
const time = targetTime - i * step;
|
|
153
153
|
const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
|
|
154
154
|
trail.push(point.x, point.y);
|
|
@@ -165,13 +165,16 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
165
165
|
...frozenB,
|
|
166
166
|
fn: (sampleT, time, params) => {
|
|
167
167
|
const a = frozenA.fn(sampleT, time, params);
|
|
168
|
-
const tB =
|
|
168
|
+
const tB =
|
|
169
|
+
frozenStrategy === "normalized"
|
|
170
|
+
? (sampleT / frozenA.period) * frozenB.period
|
|
171
|
+
: sampleT;
|
|
169
172
|
const b = frozenB.fn(tB, time, params);
|
|
170
173
|
return {
|
|
171
174
|
x: a.x + (b.x - a.x) * frozenAlpha,
|
|
172
|
-
y: a.y + (b.y - a.y) * frozenAlpha
|
|
175
|
+
y: a.y + (b.y - a.y) * frozenAlpha,
|
|
173
176
|
};
|
|
174
|
-
}
|
|
177
|
+
},
|
|
175
178
|
};
|
|
176
179
|
}
|
|
177
180
|
_morphStrategy = strategy;
|
|
@@ -184,7 +187,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
184
187
|
completeMorph() {
|
|
185
188
|
if (morphCurveB !== null) {
|
|
186
189
|
if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
|
|
187
|
-
t = t / curve.period * morphCurveB.period;
|
|
190
|
+
t = (t / curve.period) * morphCurveB.period;
|
|
188
191
|
}
|
|
189
192
|
curve = morphCurveB;
|
|
190
193
|
}
|
|
@@ -196,19 +199,22 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
196
199
|
const points = new Array(steps);
|
|
197
200
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
198
201
|
for (let i = 0; i < steps; i++) {
|
|
199
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
202
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
200
203
|
const a = sampleSkeleton(curve, sampleT);
|
|
201
|
-
const tB =
|
|
204
|
+
const tB =
|
|
205
|
+
_morphStrategy === "normalized"
|
|
206
|
+
? (sampleT / curve.period) * morphCurveB.period
|
|
207
|
+
: sampleT;
|
|
202
208
|
const b = sampleSkeleton(morphCurveB, tB);
|
|
203
209
|
points[i] = {
|
|
204
210
|
x: a.x + (b.x - a.x) * _morphAlpha,
|
|
205
|
-
y: a.y + (b.y - a.y) * _morphAlpha
|
|
211
|
+
y: a.y + (b.y - a.y) * _morphAlpha,
|
|
206
212
|
};
|
|
207
213
|
}
|
|
208
214
|
return points;
|
|
209
215
|
}
|
|
210
216
|
for (let i = 0; i < steps; i++) {
|
|
211
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
217
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
212
218
|
points[i] = sampleSkeleton(curve, sampleT);
|
|
213
219
|
}
|
|
214
220
|
return points;
|
|
@@ -250,7 +256,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
250
256
|
_speedTransition.reject(new Error("Speed transition cancelled"));
|
|
251
257
|
_speedTransition = null;
|
|
252
258
|
}
|
|
253
|
-
}
|
|
259
|
+
},
|
|
254
260
|
};
|
|
255
261
|
}
|
|
256
262
|
|
|
@@ -313,13 +319,16 @@ function computeTrailQuad(trail, i, trailCount, toX, toY) {
|
|
|
313
319
|
r1x: nx - n1.x * w1,
|
|
314
320
|
r1y: ny - n1.y * w1,
|
|
315
321
|
opacity,
|
|
316
|
-
progress
|
|
322
|
+
progress,
|
|
317
323
|
};
|
|
318
324
|
}
|
|
319
325
|
function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
320
326
|
if (pts.length === 0) return null;
|
|
321
327
|
const first = pts[0];
|
|
322
|
-
let minX = first.x,
|
|
328
|
+
let minX = first.x,
|
|
329
|
+
maxX = first.x,
|
|
330
|
+
minY = first.y,
|
|
331
|
+
maxY = first.y;
|
|
323
332
|
for (const p of pts) {
|
|
324
333
|
if (p.x < minX) {
|
|
325
334
|
minX = p.x;
|
|
@@ -338,7 +347,7 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
|
338
347
|
const h = maxY - minY;
|
|
339
348
|
if (w === 0 && h === 0) {
|
|
340
349
|
throw new Error(
|
|
341
|
-
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
350
|
+
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t.",
|
|
342
351
|
);
|
|
343
352
|
}
|
|
344
353
|
const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
|
|
@@ -349,12 +358,12 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
|
349
358
|
scaleXProportional,
|
|
350
359
|
scaleYProportional,
|
|
351
360
|
scaleXMinPadding,
|
|
352
|
-
scaleYMinPadding
|
|
361
|
+
scaleYMinPadding,
|
|
353
362
|
);
|
|
354
363
|
return {
|
|
355
364
|
scale,
|
|
356
365
|
offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
|
|
357
|
-
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
366
|
+
offsetY: (logicalHeight - h * scale) / 2 - minY * scale,
|
|
358
367
|
};
|
|
359
368
|
}
|
|
360
369
|
function enginePassthroughs(engine) {
|
|
@@ -364,33 +373,17 @@ function enginePassthroughs(engine) {
|
|
|
364
373
|
setSpeed: engine.setSpeed,
|
|
365
374
|
getSpeed: engine.getSpeed,
|
|
366
375
|
resetSpeed: engine.resetSpeed,
|
|
367
|
-
setSpeedOver: engine.setSpeedOver
|
|
376
|
+
setSpeedOver: engine.setSpeedOver,
|
|
368
377
|
};
|
|
369
378
|
}
|
|
370
|
-
var GRADIENT = {
|
|
371
|
-
bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
|
|
372
|
-
sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
|
|
373
|
-
ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
|
|
374
|
-
ice: ["#1e3a8a", "#67e8f9"],
|
|
375
|
-
fire: ["#7f1d1d", "#fbbf24"],
|
|
376
|
-
forest: ["#14532d", "#86efac"]
|
|
377
|
-
};
|
|
378
|
-
var PRESETS = {
|
|
379
|
-
bard: GRADIENT.bard,
|
|
380
|
-
sunset: GRADIENT.sunset,
|
|
381
|
-
ocean: GRADIENT.ocean,
|
|
382
|
-
ice: GRADIENT.ice,
|
|
383
|
-
fire: GRADIENT.fire,
|
|
384
|
-
forest: GRADIENT.forest
|
|
385
|
-
};
|
|
386
379
|
function hexToRgb(hex) {
|
|
387
380
|
const n = parseInt(hex.slice(1), 16);
|
|
388
|
-
return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
|
|
381
|
+
return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };
|
|
389
382
|
}
|
|
390
383
|
var lerpRgb = (a, b, t) => ({
|
|
391
384
|
r: Math.round(a.r + (b.r - a.r) * t),
|
|
392
385
|
g: Math.round(a.g + (b.g - a.g) * t),
|
|
393
|
-
b: Math.round(a.b + (b.b - a.b) * t)
|
|
386
|
+
b: Math.round(a.b + (b.b - a.b) * t),
|
|
394
387
|
});
|
|
395
388
|
function getPaletteColor(palette, position, timeOffset = 0) {
|
|
396
389
|
if (palette.length === 0) {
|
|
@@ -407,21 +400,123 @@ function getPaletteColor(palette, position, timeOffset = 0) {
|
|
|
407
400
|
const c2 = hexToRgb(palette[(idx + 1) % palette.length]);
|
|
408
401
|
return lerpRgb(c1, c2, t);
|
|
409
402
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
403
|
+
var HEX_COLOR_RE = /^#[0-9a-fA-F]{6}$/;
|
|
404
|
+
var TRAIL_STYLES = ["default", "gradient-static", "gradient-animated"];
|
|
405
|
+
var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
406
|
+
"trailColor",
|
|
407
|
+
"headColor",
|
|
408
|
+
"skeletonColor",
|
|
409
|
+
"trailStyle",
|
|
410
|
+
]);
|
|
411
|
+
function validateRenderOptions(partial) {
|
|
412
|
+
for (const key of Object.keys(partial)) {
|
|
413
|
+
if (!RENDER_OPTION_KEYS.has(key)) {
|
|
414
|
+
throw new TypeError(`[sarmal] setRenderOptions: unknown key "${key}"`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (partial.trailColor !== void 0) {
|
|
418
|
+
assertTrailColor(partial.trailColor);
|
|
419
|
+
}
|
|
420
|
+
if (partial.headColor !== void 0) {
|
|
421
|
+
assertHeadColor(partial.headColor);
|
|
422
|
+
}
|
|
423
|
+
if (partial.skeletonColor !== void 0) {
|
|
424
|
+
assertSkeletonColor(partial.skeletonColor);
|
|
413
425
|
}
|
|
414
|
-
if (
|
|
415
|
-
|
|
426
|
+
if (partial.trailStyle !== void 0) {
|
|
427
|
+
assertTrailStyle(partial.trailStyle);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function assertTrailColor(value) {
|
|
431
|
+
if (typeof value === "string") {
|
|
432
|
+
if (!HEX_COLOR_RE.test(value)) {
|
|
433
|
+
throw new TypeError(
|
|
434
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (Array.isArray(value)) {
|
|
440
|
+
if (value.length < 2) {
|
|
441
|
+
throw new RangeError(
|
|
442
|
+
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`,
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
for (let i = 0; i < value.length; i++) {
|
|
446
|
+
const entry = value[i];
|
|
447
|
+
if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
|
|
448
|
+
throw new TypeError(
|
|
449
|
+
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`,
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
throw new TypeError(
|
|
456
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`,
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
function assertHeadColor(value) {
|
|
460
|
+
if (value === null) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
464
|
+
throw new TypeError(
|
|
465
|
+
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function assertSkeletonColor(value) {
|
|
470
|
+
if (value === "transparent") {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
474
|
+
throw new TypeError(
|
|
475
|
+
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`,
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function assertTrailStyle(value) {
|
|
480
|
+
if (!TRAIL_STYLES.includes(value)) {
|
|
481
|
+
throw new RangeError(
|
|
482
|
+
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function resolveTrailMainColor(trailColor) {
|
|
487
|
+
return typeof trailColor === "string" ? trailColor : trailColor[0];
|
|
488
|
+
}
|
|
489
|
+
function resolveTrailPalette(trailColor) {
|
|
490
|
+
return typeof trailColor === "string" ? [trailColor] : trailColor;
|
|
491
|
+
}
|
|
492
|
+
function resolveHeadColor(trailColor, trailStyle) {
|
|
493
|
+
if (trailStyle === "default") {
|
|
494
|
+
return resolveTrailMainColor(trailColor);
|
|
495
|
+
}
|
|
496
|
+
const palette = resolveTrailPalette(trailColor);
|
|
497
|
+
const last = palette[palette.length - 1];
|
|
498
|
+
const { r, g, b } = hexToRgb(last);
|
|
499
|
+
return `rgb(${r},${g},${b})`;
|
|
500
|
+
}
|
|
501
|
+
function warnIfTrailColorMismatch(trailColor, trailStyle) {
|
|
502
|
+
if (trailStyle === "default" && Array.isArray(trailColor)) {
|
|
503
|
+
console.warn(
|
|
504
|
+
'[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.',
|
|
505
|
+
);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (trailStyle !== "default" && typeof trailColor === "string") {
|
|
509
|
+
console.warn(
|
|
510
|
+
`[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.`,
|
|
511
|
+
);
|
|
416
512
|
}
|
|
417
|
-
return trailStyle === "gradient-animated" ? GRADIENT.bard : GRADIENT.ice;
|
|
418
513
|
}
|
|
419
514
|
|
|
420
515
|
// src/renderer.ts
|
|
421
|
-
var
|
|
516
|
+
var WHITE_HEX = "#ffffff";
|
|
422
517
|
function hexToRgbComponents(hex) {
|
|
423
518
|
const n = parseInt(hex.slice(1), 16);
|
|
424
|
-
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
519
|
+
return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
|
|
425
520
|
}
|
|
426
521
|
function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
|
|
427
522
|
target.style.width = `${logicalWidth}px`;
|
|
@@ -436,22 +531,14 @@ function createRenderer(options) {
|
|
|
436
531
|
}
|
|
437
532
|
const ctx = canvas.getContext("2d");
|
|
438
533
|
const engine = options.engine;
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return trailColor;
|
|
448
|
-
}
|
|
449
|
-
const opts = {
|
|
450
|
-
skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,
|
|
451
|
-
trailColor,
|
|
452
|
-
headColor: options.headColor ?? defaultHeadColor()
|
|
453
|
-
};
|
|
454
|
-
const trailRgb = hexToRgbComponents(opts.trailColor);
|
|
534
|
+
let trailStyle = options.trailStyle ?? "default";
|
|
535
|
+
let trailColor = options.trailColor ?? WHITE_HEX;
|
|
536
|
+
let skeletonColor = options.skeletonColor ?? WHITE_HEX;
|
|
537
|
+
let userHeadColor = options.headColor ?? null;
|
|
538
|
+
let headColor = userHeadColor ?? resolveHeadColor(trailColor, trailStyle);
|
|
539
|
+
let trailSolidRgb = hexToRgbComponents(resolveTrailMainColor(trailColor));
|
|
540
|
+
let trailPalette = resolveTrailPalette(trailColor);
|
|
541
|
+
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
455
542
|
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
456
543
|
function setupCanvas() {
|
|
457
544
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -486,11 +573,13 @@ function createRenderer(options) {
|
|
|
486
573
|
}
|
|
487
574
|
}
|
|
488
575
|
function buildSkeletonCanvas() {
|
|
489
|
-
if (skeleton.length < 2)
|
|
576
|
+
if (skeleton.length < 2) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
490
579
|
skeletonCanvas = new OffscreenCanvas(canvas.width, canvas.height);
|
|
491
580
|
const skeletonCtx = skeletonCanvas.getContext("2d");
|
|
492
581
|
skeletonCtx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
493
|
-
skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(
|
|
582
|
+
skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
|
|
494
583
|
skeletonCtx.lineWidth = 1.5;
|
|
495
584
|
skeletonCtx.beginPath();
|
|
496
585
|
const first = skeleton[0];
|
|
@@ -502,8 +591,10 @@ function createRenderer(options) {
|
|
|
502
591
|
skeletonCtx.stroke();
|
|
503
592
|
}
|
|
504
593
|
function drawSkeletonPath(pts, opacity) {
|
|
505
|
-
if (pts.length < 2)
|
|
506
|
-
|
|
594
|
+
if (pts.length < 2) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
ctx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${opacity})`;
|
|
507
598
|
ctx.lineWidth = 1.5;
|
|
508
599
|
ctx.beginPath();
|
|
509
600
|
ctx.moveTo(pts[0].x * scale + offsetX, pts[0].y * scale + offsetY);
|
|
@@ -513,7 +604,7 @@ function createRenderer(options) {
|
|
|
513
604
|
ctx.stroke();
|
|
514
605
|
}
|
|
515
606
|
function drawSkeleton() {
|
|
516
|
-
if (
|
|
607
|
+
if (skeletonColor === "transparent") {
|
|
517
608
|
return;
|
|
518
609
|
}
|
|
519
610
|
if (engine.morphAlpha !== null) {
|
|
@@ -524,7 +615,7 @@ function createRenderer(options) {
|
|
|
524
615
|
if (skeleton.length < 2) {
|
|
525
616
|
return;
|
|
526
617
|
}
|
|
527
|
-
ctx.strokeStyle = `rgba(${hexToRgbComponents(
|
|
618
|
+
ctx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
|
|
528
619
|
ctx.lineWidth = 1.5;
|
|
529
620
|
ctx.beginPath();
|
|
530
621
|
const first = skeleton[0];
|
|
@@ -550,13 +641,13 @@ function createRenderer(options) {
|
|
|
550
641
|
i,
|
|
551
642
|
trailCount,
|
|
552
643
|
toX,
|
|
553
|
-
toY
|
|
644
|
+
toY,
|
|
554
645
|
);
|
|
555
646
|
if (trailStyle === "default") {
|
|
556
|
-
ctx.fillStyle = `rgba(${
|
|
647
|
+
ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
|
|
557
648
|
} else {
|
|
558
649
|
const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
|
|
559
|
-
const color = getPaletteColor(
|
|
650
|
+
const color = getPaletteColor(trailPalette, progress, timeOffset);
|
|
560
651
|
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;
|
|
561
652
|
}
|
|
562
653
|
ctx.beginPath();
|
|
@@ -574,8 +665,9 @@ function createRenderer(options) {
|
|
|
574
665
|
}
|
|
575
666
|
const x = head.x * scale + offsetX;
|
|
576
667
|
const y = head.y * scale + offsetY;
|
|
577
|
-
const r =
|
|
578
|
-
|
|
668
|
+
const r =
|
|
669
|
+
options.headRadius ?? Math.max(2, 3 * Math.sqrt(Math.min(logicalWidth, logicalHeight) / 160));
|
|
670
|
+
ctx.fillStyle = headColor;
|
|
579
671
|
ctx.beginPath();
|
|
580
672
|
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
581
673
|
ctx.fill();
|
|
@@ -675,7 +767,35 @@ function createRenderer(options) {
|
|
|
675
767
|
return new Promise((resolve) => {
|
|
676
768
|
morphResolve = resolve;
|
|
677
769
|
});
|
|
678
|
-
}
|
|
770
|
+
},
|
|
771
|
+
setRenderOptions(partial) {
|
|
772
|
+
validateRenderOptions(partial);
|
|
773
|
+
if (partial.trailColor !== void 0) {
|
|
774
|
+
trailColor = partial.trailColor;
|
|
775
|
+
trailSolidRgb = hexToRgbComponents(resolveTrailMainColor(trailColor));
|
|
776
|
+
trailPalette = resolveTrailPalette(trailColor);
|
|
777
|
+
}
|
|
778
|
+
if (partial.skeletonColor !== void 0) {
|
|
779
|
+
skeletonColor = partial.skeletonColor;
|
|
780
|
+
if (skeletonColor !== "transparent" && !engine.isLiveSkeleton) {
|
|
781
|
+
buildSkeletonCanvas();
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (partial.trailStyle !== void 0) {
|
|
785
|
+
trailStyle = partial.trailStyle;
|
|
786
|
+
}
|
|
787
|
+
if (partial.headColor !== void 0) {
|
|
788
|
+
userHeadColor = partial.headColor;
|
|
789
|
+
}
|
|
790
|
+
if (userHeadColor === null) {
|
|
791
|
+
headColor = resolveHeadColor(trailColor, trailStyle);
|
|
792
|
+
} else {
|
|
793
|
+
headColor = userHeadColor;
|
|
794
|
+
}
|
|
795
|
+
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
796
|
+
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
797
|
+
}
|
|
798
|
+
},
|
|
679
799
|
};
|
|
680
800
|
if (shouldAutoStart) {
|
|
681
801
|
instance.play();
|
|
@@ -686,19 +806,22 @@ function createRenderer(options) {
|
|
|
686
806
|
// src/curves/artemis2.ts
|
|
687
807
|
var TWO_PI2 = Math.PI * 2;
|
|
688
808
|
function artemis2Fn(t, _time, _params) {
|
|
689
|
-
const a = 0.35,
|
|
690
|
-
|
|
809
|
+
const a = 0.35,
|
|
810
|
+
b = 0.15,
|
|
811
|
+
ox = 0.175;
|
|
812
|
+
const s = Math.sin(t),
|
|
813
|
+
c = Math.cos(t);
|
|
691
814
|
const denom = 1 + s * s;
|
|
692
815
|
return {
|
|
693
|
-
x: c * (1 + a * c) / denom - ox,
|
|
694
|
-
y: s * c * (1 + b * c) / denom
|
|
816
|
+
x: (c * (1 + a * c)) / denom - ox,
|
|
817
|
+
y: (s * c * (1 + b * c)) / denom,
|
|
695
818
|
};
|
|
696
819
|
}
|
|
697
820
|
var artemis2 = {
|
|
698
821
|
name: "Artemis II",
|
|
699
822
|
fn: artemis2Fn,
|
|
700
823
|
period: TWO_PI2,
|
|
701
|
-
speed: 0.7
|
|
824
|
+
speed: 0.7,
|
|
702
825
|
};
|
|
703
826
|
|
|
704
827
|
// src/curves/astroid.ts
|
|
@@ -708,14 +831,14 @@ function astroidFn(t, _time, _params) {
|
|
|
708
831
|
const s = Math.sin(t);
|
|
709
832
|
return {
|
|
710
833
|
x: c * c * c,
|
|
711
|
-
y: s * s * s
|
|
834
|
+
y: s * s * s,
|
|
712
835
|
};
|
|
713
836
|
}
|
|
714
837
|
var astroid = {
|
|
715
838
|
name: "Astroid",
|
|
716
839
|
fn: astroidFn,
|
|
717
840
|
period: TWO_PI3,
|
|
718
|
-
speed: 1.1
|
|
841
|
+
speed: 1.1,
|
|
719
842
|
};
|
|
720
843
|
|
|
721
844
|
// src/curves/deltoid.ts
|
|
@@ -723,14 +846,14 @@ var TWO_PI4 = Math.PI * 2;
|
|
|
723
846
|
function deltoidFn(t, _time, _params) {
|
|
724
847
|
return {
|
|
725
848
|
x: 2 * Math.cos(t) + Math.cos(2 * t),
|
|
726
|
-
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
849
|
+
y: 2 * Math.sin(t) - Math.sin(2 * t),
|
|
727
850
|
};
|
|
728
851
|
}
|
|
729
852
|
var deltoid = {
|
|
730
853
|
name: "Deltoid",
|
|
731
854
|
fn: deltoidFn,
|
|
732
855
|
period: TWO_PI4,
|
|
733
|
-
speed: 0.9
|
|
856
|
+
speed: 0.9,
|
|
734
857
|
};
|
|
735
858
|
|
|
736
859
|
// src/curves/epicycloid3.ts
|
|
@@ -738,14 +861,14 @@ var TWO_PI5 = Math.PI * 2;
|
|
|
738
861
|
function epicycloid3Fn(t, _time, _params) {
|
|
739
862
|
return {
|
|
740
863
|
x: 4 * Math.cos(t) - Math.cos(4 * t),
|
|
741
|
-
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
864
|
+
y: 4 * Math.sin(t) - Math.sin(4 * t),
|
|
742
865
|
};
|
|
743
866
|
}
|
|
744
867
|
var epicycloid3 = {
|
|
745
868
|
name: "Epicycloid (n=3)",
|
|
746
869
|
fn: epicycloid3Fn,
|
|
747
870
|
period: TWO_PI5,
|
|
748
|
-
speed: 0.75
|
|
871
|
+
speed: 0.75,
|
|
749
872
|
};
|
|
750
873
|
|
|
751
874
|
// src/curves/epitrochoid7.ts
|
|
@@ -754,14 +877,14 @@ function epitrochoid7Fn(t, _time, _params) {
|
|
|
754
877
|
const d = 1 + 0.55 * Math.sin(t * 0.5);
|
|
755
878
|
return {
|
|
756
879
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
757
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
880
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
758
881
|
};
|
|
759
882
|
}
|
|
760
883
|
function epitrochoid7SkeletonFn(t) {
|
|
761
884
|
const d = 1.275;
|
|
762
885
|
return {
|
|
763
886
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
764
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
887
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
765
888
|
};
|
|
766
889
|
}
|
|
767
890
|
var epitrochoid7 = {
|
|
@@ -769,7 +892,7 @@ var epitrochoid7 = {
|
|
|
769
892
|
fn: epitrochoid7Fn,
|
|
770
893
|
period: TWO_PI6,
|
|
771
894
|
speed: 1.4,
|
|
772
|
-
skeletonFn: epitrochoid7SkeletonFn
|
|
895
|
+
skeletonFn: epitrochoid7SkeletonFn,
|
|
773
896
|
};
|
|
774
897
|
|
|
775
898
|
// src/curves/lissajous32.ts
|
|
@@ -778,7 +901,7 @@ function lissajous32Fn(t, time, _params) {
|
|
|
778
901
|
const phi = time * 0.45;
|
|
779
902
|
return {
|
|
780
903
|
x: Math.sin(3 * t + phi),
|
|
781
|
-
y: Math.sin(2 * t)
|
|
904
|
+
y: Math.sin(2 * t),
|
|
782
905
|
};
|
|
783
906
|
}
|
|
784
907
|
var lissajous32 = {
|
|
@@ -786,7 +909,7 @@ var lissajous32 = {
|
|
|
786
909
|
fn: lissajous32Fn,
|
|
787
910
|
period: TWO_PI7,
|
|
788
911
|
speed: 2,
|
|
789
|
-
skeleton: "live"
|
|
912
|
+
skeleton: "live",
|
|
790
913
|
};
|
|
791
914
|
|
|
792
915
|
// src/curves/lissajous43.ts
|
|
@@ -795,7 +918,7 @@ function lissajous43Fn(t, time, _params) {
|
|
|
795
918
|
const phi = time * 0.38;
|
|
796
919
|
return {
|
|
797
920
|
x: Math.sin(4 * t + phi),
|
|
798
|
-
y: Math.sin(3 * t)
|
|
921
|
+
y: Math.sin(3 * t),
|
|
799
922
|
};
|
|
800
923
|
}
|
|
801
924
|
var lissajous43 = {
|
|
@@ -803,17 +926,18 @@ var lissajous43 = {
|
|
|
803
926
|
fn: lissajous43Fn,
|
|
804
927
|
period: TWO_PI8,
|
|
805
928
|
speed: 1.8,
|
|
806
|
-
skeleton: "live"
|
|
929
|
+
skeleton: "live",
|
|
807
930
|
};
|
|
808
931
|
|
|
809
932
|
// src/curves/lame.ts
|
|
810
933
|
var TWO_PI9 = Math.PI * 2;
|
|
811
934
|
function lameFn(t, time, _params) {
|
|
812
935
|
const p = 1.75 + 1.25 * Math.sin(time * 0.48);
|
|
813
|
-
const c = Math.cos(t),
|
|
936
|
+
const c = Math.cos(t),
|
|
937
|
+
s = Math.sin(t);
|
|
814
938
|
return {
|
|
815
939
|
x: Math.sign(c) * Math.pow(Math.abs(c), p),
|
|
816
|
-
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
940
|
+
y: Math.sign(s) * Math.pow(Math.abs(s), p),
|
|
817
941
|
};
|
|
818
942
|
}
|
|
819
943
|
var lame = {
|
|
@@ -821,7 +945,7 @@ var lame = {
|
|
|
821
945
|
fn: lameFn,
|
|
822
946
|
period: TWO_PI9,
|
|
823
947
|
speed: 1,
|
|
824
|
-
skeleton: "live"
|
|
948
|
+
skeleton: "live",
|
|
825
949
|
};
|
|
826
950
|
|
|
827
951
|
// src/curves/rose3.ts
|
|
@@ -830,14 +954,14 @@ function rose3Fn(t, _time, _params) {
|
|
|
830
954
|
const r = Math.cos(3 * t);
|
|
831
955
|
return {
|
|
832
956
|
x: r * Math.cos(t),
|
|
833
|
-
y: r * Math.sin(t)
|
|
957
|
+
y: r * Math.sin(t),
|
|
834
958
|
};
|
|
835
959
|
}
|
|
836
960
|
var rose3 = {
|
|
837
961
|
name: "Rose (n=3)",
|
|
838
962
|
fn: rose3Fn,
|
|
839
963
|
period: TWO_PI10,
|
|
840
|
-
speed: 1.15
|
|
964
|
+
speed: 1.15,
|
|
841
965
|
};
|
|
842
966
|
|
|
843
967
|
// src/curves/rose5.ts
|
|
@@ -846,14 +970,14 @@ function rose5Fn(t, _time, _params) {
|
|
|
846
970
|
const r = Math.cos(5 * t);
|
|
847
971
|
return {
|
|
848
972
|
x: r * Math.cos(t),
|
|
849
|
-
y: r * Math.sin(t)
|
|
973
|
+
y: r * Math.sin(t),
|
|
850
974
|
};
|
|
851
975
|
}
|
|
852
976
|
var rose5 = {
|
|
853
977
|
name: "Rose (n=5)",
|
|
854
978
|
fn: rose5Fn,
|
|
855
979
|
period: TWO_PI11,
|
|
856
|
-
speed: 1
|
|
980
|
+
speed: 1,
|
|
857
981
|
};
|
|
858
982
|
|
|
859
983
|
// src/curves/index.ts
|
|
@@ -867,7 +991,7 @@ var curves = {
|
|
|
867
991
|
lissajous32,
|
|
868
992
|
lissajous43,
|
|
869
993
|
epicycloid3,
|
|
870
|
-
lame
|
|
994
|
+
lame,
|
|
871
995
|
};
|
|
872
996
|
|
|
873
997
|
// src/index.ts
|
|
@@ -878,14 +1002,13 @@ function createSarmal(canvas, curveDef, options) {
|
|
|
878
1002
|
}
|
|
879
1003
|
|
|
880
1004
|
// src/auto-init.ts
|
|
881
|
-
function
|
|
1005
|
+
function parseTrailColor(value) {
|
|
882
1006
|
try {
|
|
883
1007
|
const parsed = JSON.parse(value);
|
|
884
1008
|
if (Array.isArray(parsed)) {
|
|
885
1009
|
return parsed;
|
|
886
1010
|
}
|
|
887
|
-
} catch {
|
|
888
|
-
}
|
|
1011
|
+
} catch {}
|
|
889
1012
|
return value;
|
|
890
1013
|
}
|
|
891
1014
|
function init() {
|
|
@@ -900,15 +1023,16 @@ function init() {
|
|
|
900
1023
|
return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
|
|
901
1024
|
}
|
|
902
1025
|
createSarmal(canvas, curveDef, {
|
|
903
|
-
...canvas.dataset.trailColor && {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
...canvas.dataset.
|
|
907
|
-
...canvas.dataset.
|
|
908
|
-
...canvas.dataset.
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1026
|
+
...(canvas.dataset.trailColor && {
|
|
1027
|
+
trailColor: parseTrailColor(canvas.dataset.trailColor),
|
|
1028
|
+
}),
|
|
1029
|
+
...(canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor }),
|
|
1030
|
+
...(canvas.dataset.headColor && { headColor: canvas.dataset.headColor }),
|
|
1031
|
+
...(canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) }),
|
|
1032
|
+
...(canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) }),
|
|
1033
|
+
...(canvas.dataset.trailStyle && {
|
|
1034
|
+
trailStyle: canvas.dataset.trailStyle,
|
|
1035
|
+
}),
|
|
912
1036
|
});
|
|
913
1037
|
});
|
|
914
1038
|
}
|
|
@@ -920,4 +1044,4 @@ if (document.readyState === "loading") {
|
|
|
920
1044
|
requestAnimationFrame(init);
|
|
921
1045
|
}
|
|
922
1046
|
//# sourceMappingURL=auto-init.js.map
|
|
923
|
-
//# sourceMappingURL=auto-init.js.map
|
|
1047
|
+
//# sourceMappingURL=auto-init.js.map
|