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