@sarmal/core 0.12.0 → 0.14.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 +48 -21
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +48 -21
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/index.d.cts +1 -1
- package/dist/curves/index.d.ts +1 -1
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/index.cjs +88 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +88 -32
- package/dist/index.js.map +1 -1
- package/dist/{types-BzgdhxE0.d.cts → types-BQosOzlf.d.cts} +30 -14
- package/dist/{types-BzgdhxE0.d.ts → types-BQosOzlf.d.ts} +30 -14
- package/package.json +1 -1
package/dist/curves/lame.d.cts
CHANGED
package/dist/curves/lame.d.ts
CHANGED
package/dist/curves/rose3.d.cts
CHANGED
package/dist/curves/rose3.d.ts
CHANGED
package/dist/curves/rose5.d.cts
CHANGED
package/dist/curves/rose5.d.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -260,6 +260,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
260
260
|
var DEFAULT_MORPH_DURATION_MS = 300;
|
|
261
261
|
var DEFAULT_SKELETON_OPACITY = 0.15;
|
|
262
262
|
var FIT_PADDING = 0.1;
|
|
263
|
+
var FIT_PADDING_MIN = 4;
|
|
263
264
|
var TRAIL_FADE_CURVE = 1.5;
|
|
264
265
|
var TRAIL_MAX_OPACITY = 0.88;
|
|
265
266
|
var TRAIL_MIN_WIDTH = 0.5;
|
|
@@ -342,9 +343,16 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
|
342
343
|
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
343
344
|
);
|
|
344
345
|
}
|
|
345
|
-
const
|
|
346
|
-
const
|
|
347
|
-
const
|
|
346
|
+
const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
|
|
347
|
+
const scaleYProportional = logicalHeight / (h * (1 + FIT_PADDING * 2));
|
|
348
|
+
const scaleXMinPadding = (logicalWidth - FIT_PADDING_MIN * 2) / w;
|
|
349
|
+
const scaleYMinPadding = (logicalHeight - FIT_PADDING_MIN * 2) / h;
|
|
350
|
+
const scale = Math.min(
|
|
351
|
+
scaleXProportional,
|
|
352
|
+
scaleYProportional,
|
|
353
|
+
scaleXMinPadding,
|
|
354
|
+
scaleYMinPadding
|
|
355
|
+
);
|
|
348
356
|
return {
|
|
349
357
|
scale,
|
|
350
358
|
offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
|
|
@@ -361,9 +369,6 @@ function enginePassthroughs(engine) {
|
|
|
361
369
|
setSpeedOver: engine.setSpeedOver
|
|
362
370
|
};
|
|
363
371
|
}
|
|
364
|
-
|
|
365
|
-
// src/renderer.ts
|
|
366
|
-
var DEFAULT_SKELETON_COLOR = "#ffffff";
|
|
367
372
|
var GRADIENT = {
|
|
368
373
|
bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
|
|
369
374
|
sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
|
|
@@ -390,8 +395,12 @@ var lerpRgb = (a, b, t) => ({
|
|
|
390
395
|
b: Math.round(a.b + (b.b - a.b) * t)
|
|
391
396
|
});
|
|
392
397
|
function getPaletteColor(palette, position, timeOffset = 0) {
|
|
393
|
-
if (palette.length === 0)
|
|
394
|
-
|
|
398
|
+
if (palette.length === 0) {
|
|
399
|
+
return { r: 255, g: 255, b: 255 };
|
|
400
|
+
}
|
|
401
|
+
if (palette.length === 1) {
|
|
402
|
+
return hexToRgb(palette[0]);
|
|
403
|
+
}
|
|
395
404
|
const cyclePos = (position + timeOffset) % 1;
|
|
396
405
|
const scaled = cyclePos * palette.length;
|
|
397
406
|
const idx = Math.floor(scaled);
|
|
@@ -401,10 +410,17 @@ function getPaletteColor(palette, position, timeOffset = 0) {
|
|
|
401
410
|
return lerpRgb(c1, c2, t);
|
|
402
411
|
}
|
|
403
412
|
function resolvePalette(palette, trailStyle) {
|
|
404
|
-
if (Array.isArray(palette))
|
|
405
|
-
|
|
413
|
+
if (Array.isArray(palette)) {
|
|
414
|
+
return palette;
|
|
415
|
+
}
|
|
416
|
+
if (palette && palette in PRESETS) {
|
|
417
|
+
return PRESETS[palette];
|
|
418
|
+
}
|
|
406
419
|
return trailStyle === "gradient-animated" ? GRADIENT.bard : GRADIENT.ice;
|
|
407
420
|
}
|
|
421
|
+
|
|
422
|
+
// src/renderer.ts
|
|
423
|
+
var DEFAULT_SKELETON_COLOR = "#ffffff";
|
|
408
424
|
function hexToRgbComponents(hex) {
|
|
409
425
|
const n = parseInt(hex.slice(1), 16);
|
|
410
426
|
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
@@ -566,10 +582,7 @@ function createRenderer(options) {
|
|
|
566
582
|
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
567
583
|
ctx.fill();
|
|
568
584
|
}
|
|
569
|
-
function
|
|
570
|
-
const now = performance.now();
|
|
571
|
-
const deltaTime = Math.min((now - lastTime) / 1e3, 1 / 30);
|
|
572
|
-
lastTime = now;
|
|
585
|
+
function renderFrame(deltaTime) {
|
|
573
586
|
if (trailStyle === "gradient-animated") {
|
|
574
587
|
gradientAnimTime += deltaTime * 1e3;
|
|
575
588
|
}
|
|
@@ -605,22 +618,33 @@ function createRenderer(options) {
|
|
|
605
618
|
drawSkeleton();
|
|
606
619
|
drawTrail();
|
|
607
620
|
drawHead();
|
|
608
|
-
|
|
621
|
+
}
|
|
622
|
+
function loop() {
|
|
623
|
+
const now = performance.now();
|
|
624
|
+
const deltaTime = Math.min((now - lastTime) / 1e3, 1 / 30);
|
|
625
|
+
lastTime = now;
|
|
626
|
+
renderFrame(deltaTime);
|
|
627
|
+
animationId = requestAnimationFrame(loop);
|
|
609
628
|
}
|
|
610
629
|
skeleton = engine.getSarmalSkeleton();
|
|
611
630
|
calculateBoundaries();
|
|
612
631
|
if (!engine.isLiveSkeleton) {
|
|
613
632
|
buildSkeletonCanvas();
|
|
614
633
|
}
|
|
615
|
-
|
|
616
|
-
|
|
634
|
+
if (options.initialT !== void 0) {
|
|
635
|
+
engine.seek(options.initialT);
|
|
636
|
+
}
|
|
637
|
+
renderFrame(0);
|
|
638
|
+
const shouldAutoStart = options.autoStart !== false;
|
|
639
|
+
const instance = {
|
|
640
|
+
play() {
|
|
617
641
|
if (animationId !== null) {
|
|
618
642
|
return;
|
|
619
643
|
}
|
|
620
644
|
lastTime = performance.now();
|
|
621
|
-
|
|
645
|
+
loop();
|
|
622
646
|
},
|
|
623
|
-
|
|
647
|
+
pause() {
|
|
624
648
|
if (animationId === null) {
|
|
625
649
|
return;
|
|
626
650
|
}
|
|
@@ -655,6 +679,10 @@ function createRenderer(options) {
|
|
|
655
679
|
});
|
|
656
680
|
}
|
|
657
681
|
};
|
|
682
|
+
if (shouldAutoStart) {
|
|
683
|
+
instance.play();
|
|
684
|
+
}
|
|
685
|
+
return instance;
|
|
658
686
|
}
|
|
659
687
|
|
|
660
688
|
// src/renderer-svg.ts
|
|
@@ -686,10 +714,15 @@ function el(tag) {
|
|
|
686
714
|
function createSVGRenderer(options) {
|
|
687
715
|
const { container, engine } = options;
|
|
688
716
|
const trailColor = options.trailColor ?? "#ffffff";
|
|
717
|
+
const trailStyle = options.trailStyle ?? "default";
|
|
718
|
+
const palette = resolvePalette(options.palette, trailStyle);
|
|
689
719
|
const opts = {
|
|
690
720
|
skeletonColor: options.skeletonColor ?? "#ffffff",
|
|
691
721
|
trailColor,
|
|
692
|
-
headColor: options.headColor ??
|
|
722
|
+
headColor: options.headColor ?? (trailStyle !== "default" ? (() => {
|
|
723
|
+
const { r, g, b } = getPaletteColor(palette, 1);
|
|
724
|
+
return `rgb(${r},${g},${b})`;
|
|
725
|
+
})() : trailColor),
|
|
693
726
|
ariaLabel: options.ariaLabel ?? "Loading"
|
|
694
727
|
};
|
|
695
728
|
const rect = container.getBoundingClientRect();
|
|
@@ -706,6 +739,7 @@ function createSVGRenderer(options) {
|
|
|
706
739
|
titleEl.textContent = opts.ariaLabel;
|
|
707
740
|
svg.appendChild(titleEl);
|
|
708
741
|
const skeletonPath = el("path");
|
|
742
|
+
skeletonPath.setAttribute("data-sarmal-role", "skeleton");
|
|
709
743
|
skeletonPath.setAttribute("fill", "none");
|
|
710
744
|
skeletonPath.setAttribute("stroke", opts.skeletonColor);
|
|
711
745
|
skeletonPath.setAttribute("stroke-opacity", String(DEFAULT_SKELETON_OPACITY));
|
|
@@ -733,10 +767,12 @@ function createSVGRenderer(options) {
|
|
|
733
767
|
trailPaths.push(path);
|
|
734
768
|
}
|
|
735
769
|
const headCircle = el("circle");
|
|
770
|
+
headCircle.setAttribute("data-sarmal-role", "head");
|
|
736
771
|
headCircle.setAttribute("fill", opts.headColor);
|
|
737
772
|
headCircle.setAttribute("r", String(headRadius));
|
|
738
773
|
svg.appendChild(headCircle);
|
|
739
774
|
container.appendChild(svg);
|
|
775
|
+
let gradientAnimTime = 0;
|
|
740
776
|
let scale = 1;
|
|
741
777
|
let offsetX = 0;
|
|
742
778
|
let offsetY = 0;
|
|
@@ -770,7 +806,7 @@ function createSVGRenderer(options) {
|
|
|
770
806
|
return;
|
|
771
807
|
}
|
|
772
808
|
for (let i = 0; i < trailCount - 1; i++) {
|
|
773
|
-
const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity } = computeTrailQuad(
|
|
809
|
+
const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity, progress } = computeTrailQuad(
|
|
774
810
|
trail,
|
|
775
811
|
i,
|
|
776
812
|
trailCount,
|
|
@@ -780,6 +816,11 @@ function createSVGRenderer(options) {
|
|
|
780
816
|
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`;
|
|
781
817
|
trailPaths[i].setAttribute("d", d);
|
|
782
818
|
trailPaths[i].setAttribute("fill-opacity", opacity.toFixed(3));
|
|
819
|
+
if (trailStyle !== "default") {
|
|
820
|
+
const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
|
|
821
|
+
const { r, g, b } = getPaletteColor(palette, progress, timeOffset);
|
|
822
|
+
trailPaths[i].setAttribute("fill", `rgb(${r},${g},${b})`);
|
|
823
|
+
}
|
|
783
824
|
}
|
|
784
825
|
for (let i = trailCount - 1; i < trailPaths.length; i++) {
|
|
785
826
|
trailPaths[i].setAttribute("d", "");
|
|
@@ -802,12 +843,12 @@ function createSVGRenderer(options) {
|
|
|
802
843
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
803
844
|
let morphTarget = null;
|
|
804
845
|
let morphAlpha = 0;
|
|
805
|
-
function renderFrame() {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
846
|
+
function renderFrame(deltaTime) {
|
|
847
|
+
if (trailStyle === "gradient-animated") {
|
|
848
|
+
gradientAnimTime += deltaTime * 1e3;
|
|
849
|
+
}
|
|
809
850
|
if (engine.morphAlpha !== null) {
|
|
810
|
-
morphAlpha = Math.min(1, morphAlpha +
|
|
851
|
+
morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1e3));
|
|
811
852
|
engine.setMorphAlpha(morphAlpha);
|
|
812
853
|
if (morphPathABuilt) {
|
|
813
854
|
skeletonPathA.setAttribute("d", morphPathABuilt);
|
|
@@ -837,7 +878,7 @@ function createSVGRenderer(options) {
|
|
|
837
878
|
updateSkeleton(newSkeleton);
|
|
838
879
|
}
|
|
839
880
|
}
|
|
840
|
-
const trail = engine.tick(
|
|
881
|
+
const trail = engine.tick(deltaTime);
|
|
841
882
|
const trailCount = engine.trailCount;
|
|
842
883
|
if (engine.isLiveSkeleton && engine.morphAlpha === null) {
|
|
843
884
|
const liveSkeleton = engine.getSarmalSkeleton();
|
|
@@ -846,19 +887,30 @@ function createSVGRenderer(options) {
|
|
|
846
887
|
}
|
|
847
888
|
updateTrail(trail, trailCount);
|
|
848
889
|
updateHead(trail, trailCount);
|
|
890
|
+
}
|
|
891
|
+
function loop() {
|
|
892
|
+
const now = performance.now();
|
|
893
|
+
const deltaTime = Math.min((now - lastTime) / 1e3, 1 / 30);
|
|
894
|
+
lastTime = now;
|
|
895
|
+
renderFrame(deltaTime);
|
|
849
896
|
if (!prefersReducedMotion) {
|
|
850
|
-
animationId = requestAnimationFrame(
|
|
897
|
+
animationId = requestAnimationFrame(loop);
|
|
851
898
|
}
|
|
852
899
|
}
|
|
853
|
-
|
|
854
|
-
|
|
900
|
+
if (options.initialT !== void 0) {
|
|
901
|
+
engine.seek(options.initialT);
|
|
902
|
+
}
|
|
903
|
+
renderFrame(0);
|
|
904
|
+
const shouldAutoStart = options.autoStart !== false;
|
|
905
|
+
const instance = {
|
|
906
|
+
play() {
|
|
855
907
|
if (animationId !== null) {
|
|
856
908
|
return;
|
|
857
909
|
}
|
|
858
910
|
lastTime = performance.now();
|
|
859
|
-
|
|
911
|
+
loop();
|
|
860
912
|
},
|
|
861
|
-
|
|
913
|
+
pause() {
|
|
862
914
|
if (animationId === null) {
|
|
863
915
|
return;
|
|
864
916
|
}
|
|
@@ -901,6 +953,10 @@ function createSVGRenderer(options) {
|
|
|
901
953
|
});
|
|
902
954
|
}
|
|
903
955
|
};
|
|
956
|
+
if (shouldAutoStart) {
|
|
957
|
+
instance.play();
|
|
958
|
+
}
|
|
959
|
+
return instance;
|
|
904
960
|
}
|
|
905
961
|
function createSarmalSVG(container, curveDef, options) {
|
|
906
962
|
const { trailLength, ...rendererOpts } = options ?? {};
|