@sarmal/core 0.34.0 → 0.35.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/index.cjs +100 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +100 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1418,7 +1418,6 @@ function createSarmalSVG(container, curveDef, options) {
|
|
|
1418
1418
|
}
|
|
1419
1419
|
|
|
1420
1420
|
// src/renderer-dot-matrix.ts
|
|
1421
|
-
var NUM_BUCKETS = 8;
|
|
1422
1421
|
function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
1423
1422
|
const {
|
|
1424
1423
|
cols = 32,
|
|
@@ -1457,7 +1456,12 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1457
1456
|
let scale = 1;
|
|
1458
1457
|
let offsetX = 0;
|
|
1459
1458
|
let offsetY = 0;
|
|
1460
|
-
let
|
|
1459
|
+
let pixelMaskStarts = new Uint32Array(0);
|
|
1460
|
+
let pixelMaskLengths = new Uint32Array(0);
|
|
1461
|
+
let pixelMaskIndices = new Uint32Array(0);
|
|
1462
|
+
let pixelMaskCoverages = new Float32Array(0);
|
|
1463
|
+
let bgImageData = null;
|
|
1464
|
+
let frameImageData = null;
|
|
1461
1465
|
let animationId = null;
|
|
1462
1466
|
let lastTime = 0;
|
|
1463
1467
|
let pausedByVisibility = false;
|
|
@@ -1465,20 +1469,73 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1465
1469
|
let morphReject = null;
|
|
1466
1470
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
1467
1471
|
let morphProgress = 0;
|
|
1468
|
-
function
|
|
1469
|
-
|
|
1470
|
-
const
|
|
1471
|
-
const
|
|
1472
|
-
|
|
1473
|
-
|
|
1472
|
+
function computePixelMask() {
|
|
1473
|
+
const starts = new Uint32Array(cols * rows);
|
|
1474
|
+
const lengths = new Uint32Array(cols * rows);
|
|
1475
|
+
const allIndices = [];
|
|
1476
|
+
const allCoverages = [];
|
|
1477
|
+
const cornerR = roundness * dotR;
|
|
1478
|
+
const cornerR2 = cornerR * cornerR;
|
|
1479
|
+
const SSAA = 4;
|
|
1480
|
+
const SSAA2 = SSAA * SSAA;
|
|
1474
1481
|
for (let row = 0; row < rows; row++) {
|
|
1475
1482
|
for (let col = 0; col < cols; col++) {
|
|
1483
|
+
const dotIdx = row * cols + col;
|
|
1476
1484
|
const cx = (col + 0.5) * cellW;
|
|
1477
1485
|
const cy = (row + 0.5) * cellH;
|
|
1478
|
-
|
|
1486
|
+
const x0 = Math.max(0, Math.floor(cx - dotR - 1));
|
|
1487
|
+
const x1 = Math.min(W - 1, Math.ceil(cx + dotR + 1));
|
|
1488
|
+
const y0 = Math.max(0, Math.floor(cy - dotR - 1));
|
|
1489
|
+
const y1 = Math.min(H - 1, Math.ceil(cy + dotR + 1));
|
|
1490
|
+
starts[dotIdx] = allIndices.length;
|
|
1491
|
+
let count = 0;
|
|
1492
|
+
for (let py = y0; py <= y1; py++) {
|
|
1493
|
+
for (let px = x0; px <= x1; px++) {
|
|
1494
|
+
let hits = 0;
|
|
1495
|
+
for (let sy = 0; sy < SSAA; sy++) {
|
|
1496
|
+
const spyCenter = py + (sy + 0.5) / SSAA;
|
|
1497
|
+
for (let sx = 0; sx < SSAA; sx++) {
|
|
1498
|
+
const spxCenter = px + (sx + 0.5) / SSAA;
|
|
1499
|
+
const dx = Math.max(Math.abs(spxCenter - cx) - (dotR - cornerR), 0);
|
|
1500
|
+
const dy = Math.max(Math.abs(spyCenter - cy) - (dotR - cornerR), 0);
|
|
1501
|
+
if (dx * dx + dy * dy <= cornerR2) {
|
|
1502
|
+
hits++;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
if (hits > 0) {
|
|
1507
|
+
allIndices.push((py * W + px) * 4);
|
|
1508
|
+
allCoverages.push(hits / SSAA2);
|
|
1509
|
+
count++;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
lengths[dotIdx] = count;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
pixelMaskStarts = starts;
|
|
1517
|
+
pixelMaskLengths = lengths;
|
|
1518
|
+
pixelMaskIndices = new Uint32Array(allIndices);
|
|
1519
|
+
pixelMaskCoverages = new Float32Array(allCoverages);
|
|
1520
|
+
}
|
|
1521
|
+
function buildBgImageData() {
|
|
1522
|
+
bgImageData = new ImageData(W, H);
|
|
1523
|
+
const bg = gradientRgb ? gradientRgb[0] : colorRgb;
|
|
1524
|
+
const baseAlpha = 0.05 * 255;
|
|
1525
|
+
const { data } = bgImageData;
|
|
1526
|
+
const n = cols * rows;
|
|
1527
|
+
for (let dotIdx = 0; dotIdx < n; dotIdx++) {
|
|
1528
|
+
const start = pixelMaskStarts[dotIdx];
|
|
1529
|
+
const len = pixelMaskLengths[dotIdx];
|
|
1530
|
+
for (let k = 0; k < len; k++) {
|
|
1531
|
+
const px = pixelMaskIndices[start + k];
|
|
1532
|
+
const coverage = pixelMaskCoverages[start + k];
|
|
1533
|
+
data[px] = bg.r;
|
|
1534
|
+
data[px + 1] = bg.g;
|
|
1535
|
+
data[px + 2] = bg.b;
|
|
1536
|
+
data[px + 3] = Math.round(baseAlpha * coverage);
|
|
1479
1537
|
}
|
|
1480
1538
|
}
|
|
1481
|
-
bgCtx.fill();
|
|
1482
1539
|
}
|
|
1483
1540
|
function sampleGradientRgb(stops, t) {
|
|
1484
1541
|
const n = stops.length;
|
|
@@ -1540,43 +1597,38 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1540
1597
|
}
|
|
1541
1598
|
}
|
|
1542
1599
|
function draw() {
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
ctx.drawImage(bgCanvas, 0, 0);
|
|
1600
|
+
if (!bgImageData || !frameImageData) {
|
|
1601
|
+
return;
|
|
1546
1602
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
const
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
ctx.fillStyle = `rgb(${r},${g},${b})`;
|
|
1574
|
-
}
|
|
1575
|
-
ctx.globalAlpha = alpha;
|
|
1576
|
-
ctx.fill();
|
|
1603
|
+
frameImageData.data.set(bgImageData.data);
|
|
1604
|
+
const { data } = frameImageData;
|
|
1605
|
+
const sineOffset = currentTrailStyle === "gradient-animated" ? 0.15 * Math.sin(animTime / ANIM_PERIOD * 2 * Math.PI) : 0;
|
|
1606
|
+
const n = cols * rows;
|
|
1607
|
+
for (let dotIdx = 0; dotIdx < n; dotIdx++) {
|
|
1608
|
+
const intensity = grid[dotIdx];
|
|
1609
|
+
if (intensity <= 0) {
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
let r, g, b;
|
|
1613
|
+
if (gradientRgb !== null) {
|
|
1614
|
+
const t = Math.max(0, Math.min(1, intensity + sineOffset));
|
|
1615
|
+
({ r, g, b } = sampleGradientRgb(gradientRgb, t));
|
|
1616
|
+
} else {
|
|
1617
|
+
({ r, g, b } = colorRgb);
|
|
1618
|
+
}
|
|
1619
|
+
const baseA = (0.08 + intensity * 0.92) * 255;
|
|
1620
|
+
const start = pixelMaskStarts[dotIdx];
|
|
1621
|
+
const len = pixelMaskLengths[dotIdx];
|
|
1622
|
+
for (let k = 0; k < len; k++) {
|
|
1623
|
+
const px = pixelMaskIndices[start + k];
|
|
1624
|
+
const coverage = pixelMaskCoverages[start + k];
|
|
1625
|
+
data[px] = r;
|
|
1626
|
+
data[px + 1] = g;
|
|
1627
|
+
data[px + 2] = b;
|
|
1628
|
+
data[px + 3] = Math.round(baseA * coverage);
|
|
1577
1629
|
}
|
|
1578
1630
|
}
|
|
1579
|
-
ctx.
|
|
1631
|
+
ctx.putImageData(frameImageData, 0, 0);
|
|
1580
1632
|
}
|
|
1581
1633
|
function renderFrame(deltaTime) {
|
|
1582
1634
|
if (engine.morphAlpha !== null) {
|
|
@@ -1607,7 +1659,9 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1607
1659
|
animationId = requestAnimationFrame(loop);
|
|
1608
1660
|
}
|
|
1609
1661
|
calculateBoundaries(engine.getSarmalSkeleton());
|
|
1610
|
-
|
|
1662
|
+
computePixelMask();
|
|
1663
|
+
frameImageData = new ImageData(W, H);
|
|
1664
|
+
buildBgImageData();
|
|
1611
1665
|
if (initialPhase !== void 0) {
|
|
1612
1666
|
engine.seek(initialPhase);
|
|
1613
1667
|
}
|
|
@@ -1693,7 +1747,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1693
1747
|
}
|
|
1694
1748
|
}
|
|
1695
1749
|
if (needsRebuildBg) {
|
|
1696
|
-
|
|
1750
|
+
buildBgImageData();
|
|
1697
1751
|
}
|
|
1698
1752
|
if (currentTrailStyle !== "default" && gradientRgb === null) {
|
|
1699
1753
|
console.warn(
|