asciify-engine 1.0.16 → 1.0.17

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 CHANGED
@@ -832,7 +832,7 @@ async function asciifyVideo(source, canvas, { fontSize = 10, style = "classic",
832
832
  cancelAnimationFrame(animId);
833
833
  };
834
834
  }
835
- var EMBED_CDN_VERSION = "1.0.16";
835
+ var EMBED_CDN_VERSION = "1.0.17";
836
836
  function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
837
837
  const o = {
838
838
  r: rows,
@@ -1417,6 +1417,216 @@ function renderAuroraBackground(ctx, width, height, time, mousePos = { x: 0.5, y
1417
1417
  }
1418
1418
  }
1419
1419
  }
1420
+ function renderSilkBackground(ctx, width, height, time, options = {}) {
1421
+ const {
1422
+ fontSize = 13,
1423
+ color,
1424
+ accentColor = "#d4ff00",
1425
+ speed = 0.4,
1426
+ layers = 4,
1427
+ turbulence = 0.8,
1428
+ lightMode = false
1429
+ } = options;
1430
+ const charW = fontSize * 0.62;
1431
+ const lineH = fontSize * 1.4;
1432
+ const cols = Math.ceil(width / charW);
1433
+ const rows = Math.ceil(height / lineH);
1434
+ ctx.clearRect(0, 0, width, height);
1435
+ ctx.font = `${fontSize}px monospace`;
1436
+ ctx.textBaseline = "top";
1437
+ let cr = 255, cg = 255, cb = 255;
1438
+ if (lightMode) {
1439
+ cr = 0;
1440
+ cg = 0;
1441
+ cb = 0;
1442
+ }
1443
+ if (color) {
1444
+ const p = _parseColor(color);
1445
+ if (p) {
1446
+ cr = p.r;
1447
+ cg = p.g;
1448
+ cb = p.b;
1449
+ }
1450
+ }
1451
+ let acR = 212, acG = 255, acB = 0;
1452
+ const ap = _parseColor(accentColor);
1453
+ if (ap) {
1454
+ acR = ap.r;
1455
+ acG = ap.g;
1456
+ acB = ap.b;
1457
+ }
1458
+ const t = time * speed;
1459
+ const dirChars = ["\u2500", "\u2500", "\u254C", "\xB7", "\u254C", "\u2500", "\u2500", "\u254C", "\xB7"];
1460
+ for (let row = 0; row < rows; row++) {
1461
+ const ny = row / rows;
1462
+ for (let col = 0; col < cols; col++) {
1463
+ const nx = col / cols;
1464
+ let angleSum = 0;
1465
+ let intensitySum = 0;
1466
+ for (let l = 0; l < layers; l++) {
1467
+ const ls = _hash2(l * 13, l * 7 + 3);
1468
+ const ls2 = _hash2(l * 29, l * 11 + 1);
1469
+ const fx = 1.1 + ls * 2.4;
1470
+ const fy = 0.9 + ls2 * 2;
1471
+ const ph = ls * Math.PI * 6;
1472
+ const dr = (0.2 + _hash2(l * 41, l * 17) * 0.5) * (l % 2 === 0 ? 1 : -1.3);
1473
+ const u = Math.sin(nx * fx * Math.PI * 2 + t * dr + ph);
1474
+ const v = Math.cos(ny * fy * Math.PI * 2 + t * dr * 0.6 + ph * 1.7);
1475
+ const cross = Math.sin(nx * fy * Math.PI * turbulence + ny * fx * Math.PI * turbulence + t * dr * 0.4);
1476
+ angleSum += Math.atan2(v + cross * 0.3, u);
1477
+ intensitySum += (u * v + 1) * 0.5;
1478
+ }
1479
+ const angle = angleSum / layers;
1480
+ const intensity = Math.min(1, intensitySum / layers);
1481
+ if (intensity < 0.1) continue;
1482
+ const angleNorm = (angle + Math.PI) / (Math.PI * 2);
1483
+ const charIdx = Math.floor(angleNorm * dirChars.length) % dirChars.length;
1484
+ const ch = dirChars[charIdx];
1485
+ const isAccent = intensity > 0.8;
1486
+ const alpha = lightMode ? intensity * 0.16 : intensity * 0.13;
1487
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.44 : 0.26})` : `rgba(${cr},${cg},${cb},${alpha})`;
1488
+ ctx.fillText(ch, col * charW, row * lineH);
1489
+ }
1490
+ }
1491
+ }
1492
+ function renderVoidBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
1493
+ const {
1494
+ fontSize = 13,
1495
+ chars = " \xB7:;=+*#%@",
1496
+ color,
1497
+ accentColor = "#d4ff00",
1498
+ speed = 1,
1499
+ radius = 0.38,
1500
+ swirl = 3,
1501
+ lightMode = false
1502
+ } = options;
1503
+ const charW = fontSize * 0.62;
1504
+ const lineH = fontSize * 1.4;
1505
+ const cols = Math.ceil(width / charW);
1506
+ const rows = Math.ceil(height / lineH);
1507
+ const aspect = width / height;
1508
+ ctx.clearRect(0, 0, width, height);
1509
+ ctx.font = `${fontSize}px monospace`;
1510
+ ctx.textBaseline = "top";
1511
+ let cr = 255, cg = 255, cb = 255;
1512
+ if (lightMode) {
1513
+ cr = 0;
1514
+ cg = 0;
1515
+ cb = 0;
1516
+ }
1517
+ if (color) {
1518
+ const p = _parseColor(color);
1519
+ if (p) {
1520
+ cr = p.r;
1521
+ cg = p.g;
1522
+ cb = p.b;
1523
+ }
1524
+ }
1525
+ let acR = 212, acG = 255, acB = 0;
1526
+ const ap = _parseColor(accentColor);
1527
+ if (ap) {
1528
+ acR = ap.r;
1529
+ acG = ap.g;
1530
+ acB = ap.b;
1531
+ }
1532
+ const t = time * speed;
1533
+ for (let row = 0; row < rows; row++) {
1534
+ const ny = row / rows;
1535
+ for (let col = 0; col < cols; col++) {
1536
+ const nx = col / cols;
1537
+ const dx = (nx - mousePos.x) * aspect;
1538
+ const dy = ny - mousePos.y;
1539
+ const dist = Math.sqrt(dx * dx + dy * dy);
1540
+ const r = dist / radius;
1541
+ if (r > 1) {
1542
+ const outerNoise = _hash2(col * 3, row * 7) * Math.max(0, 1 - (r - 1) * 3);
1543
+ if (outerNoise < 0.62) continue;
1544
+ const alpha2 = outerNoise * (lightMode ? 0.05 : 0.04);
1545
+ const ch2 = chars[1];
1546
+ ctx.fillStyle = `rgba(${cr},${cg},${cb},${alpha2})`;
1547
+ ctx.fillText(ch2, col * charW, row * lineH);
1548
+ continue;
1549
+ }
1550
+ const baseAngle = Math.atan2(dy, dx * aspect);
1551
+ const swirlAmt = (1 - r) * swirl;
1552
+ const angle = baseAngle + swirlAmt + t * 0.4;
1553
+ const pulseRing = Math.max(0, 1 - Math.abs(r - (0.15 + 0.12 * Math.sin(t * 1.1))) / 0.07);
1554
+ const gravity = Math.pow(1 - r, 2.2);
1555
+ const intensity = Math.min(1, gravity + pulseRing * 0.6);
1556
+ if (intensity < 0.06) continue;
1557
+ const angleIdx = Math.floor((angle % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2) * 4);
1558
+ const densityI = Math.floor(intensity * (chars.length - 1));
1559
+ const charIdx = Math.min(chars.length - 1, densityI);
1560
+ const ch = chars[charIdx + (angleIdx > 2 && densityI > 2 ? 0 : 0)];
1561
+ const isAccent = pulseRing > 0.35 || r < 0.08;
1562
+ const alpha = lightMode ? intensity * 0.22 : intensity * 0.18;
1563
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.55 : 0.38})` : `rgba(${cr},${cg},${cb},${alpha})`;
1564
+ ctx.fillText(ch, col * charW, row * lineH);
1565
+ }
1566
+ }
1567
+ }
1568
+ function renderMorphBackground(ctx, width, height, time, options = {}) {
1569
+ const {
1570
+ fontSize = 14,
1571
+ chars = " \xB7\u2219\u2022:-=+*#",
1572
+ color,
1573
+ accentColor = "#d4ff00",
1574
+ speed = 0.5,
1575
+ harmonics = 3,
1576
+ lightMode = false
1577
+ } = options;
1578
+ const charW = fontSize * 0.62;
1579
+ const lineH = fontSize * 1.4;
1580
+ const cols = Math.ceil(width / charW);
1581
+ const rows = Math.ceil(height / lineH);
1582
+ ctx.clearRect(0, 0, width, height);
1583
+ ctx.font = `${fontSize}px monospace`;
1584
+ ctx.textBaseline = "top";
1585
+ let cr = 255, cg = 255, cb = 255;
1586
+ if (lightMode) {
1587
+ cr = 0;
1588
+ cg = 0;
1589
+ cb = 0;
1590
+ }
1591
+ if (color) {
1592
+ const p = _parseColor(color);
1593
+ if (p) {
1594
+ cr = p.r;
1595
+ cg = p.g;
1596
+ cb = p.b;
1597
+ }
1598
+ }
1599
+ let acR = 212, acG = 255, acB = 0;
1600
+ const ap = _parseColor(accentColor);
1601
+ if (ap) {
1602
+ acR = ap.r;
1603
+ acG = ap.g;
1604
+ acB = ap.b;
1605
+ }
1606
+ const t = time * speed;
1607
+ for (let row = 0; row < rows; row++) {
1608
+ for (let col = 0; col < cols; col++) {
1609
+ let v = 0;
1610
+ for (let h = 0; h < harmonics; h++) {
1611
+ const fBase = _hash2(col * (h + 3) + 7, row * (h + 5) + 11);
1612
+ const fineF = 0.18 + fBase * 1.4;
1613
+ const phase = _hash2(col * (h + 7), row * (h + 9) + 3) * Math.PI * 2;
1614
+ const weight = 1 / (h + 1);
1615
+ v += Math.sin(t * fineF + phase) * weight;
1616
+ }
1617
+ const maxV = Array.from({ length: harmonics }, (_, h) => 1 / (h + 1)).reduce((a, b) => a + b, 0);
1618
+ const norm = (v / maxV + 1) * 0.5;
1619
+ if (norm < 0.28) continue;
1620
+ const remapped = (norm - 0.28) / 0.72;
1621
+ const charIdx = Math.min(chars.length - 1, Math.floor(remapped * chars.length));
1622
+ const ch = chars[charIdx];
1623
+ const isAccent = norm > 0.88;
1624
+ const alpha = lightMode ? remapped * 0.17 : remapped * 0.13;
1625
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.45 : 0.28})` : `rgba(${cr},${cg},${cb},${alpha})`;
1626
+ ctx.fillText(ch, col * charW, row * lineH);
1627
+ }
1628
+ }
1629
+ }
1420
1630
  function _parseColor(c) {
1421
1631
  const hex = c.match(/^#([0-9a-f]{3,8})$/i)?.[1];
1422
1632
  if (hex) {
@@ -1505,6 +1715,21 @@ function asciiBackground(target, options = {}) {
1505
1715
  lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1506
1716
  color: color ?? renderOpts.color
1507
1717
  });
1718
+ const buildSilkOpts = () => ({
1719
+ ...renderOpts,
1720
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1721
+ color: color ?? renderOpts.color
1722
+ });
1723
+ const buildVoidOpts = () => ({
1724
+ ...renderOpts,
1725
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1726
+ color: color ?? renderOpts.color
1727
+ });
1728
+ const buildMorphOpts = () => ({
1729
+ ...renderOpts,
1730
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1731
+ color: color ?? renderOpts.color
1732
+ });
1508
1733
  const optsRef = { current: buildWaveOpts() };
1509
1734
  const rebuildOpts = () => {
1510
1735
  if (type === "rain") optsRef.current = buildRainOpts();
@@ -1513,6 +1738,9 @@ function asciiBackground(target, options = {}) {
1513
1738
  else if (type === "noise") optsRef.current = buildNoiseOpts();
1514
1739
  else if (type === "grid") optsRef.current = buildGridOpts();
1515
1740
  else if (type === "aurora") optsRef.current = buildAuroraOpts();
1741
+ else if (type === "silk") optsRef.current = buildSilkOpts();
1742
+ else if (type === "void") optsRef.current = buildVoidOpts();
1743
+ else if (type === "morph") optsRef.current = buildMorphOpts();
1516
1744
  else optsRef.current = buildWaveOpts();
1517
1745
  };
1518
1746
  rebuildOpts();
@@ -1553,6 +1781,12 @@ function asciiBackground(target, options = {}) {
1553
1781
  renderGridBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1554
1782
  } else if (type === "aurora") {
1555
1783
  renderAuroraBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1784
+ } else if (type === "silk") {
1785
+ renderSilkBackground(ctx, r.width, r.height, time, optsRef.current);
1786
+ } else if (type === "void") {
1787
+ renderVoidBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1788
+ } else if (type === "morph") {
1789
+ renderMorphBackground(ctx, r.width, r.height, time, optsRef.current);
1556
1790
  } else {
1557
1791
  renderWaveBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1558
1792
  }
@@ -2037,10 +2271,13 @@ exports.mountWaveBackground = mountWaveBackground;
2037
2271
  exports.renderAuroraBackground = renderAuroraBackground;
2038
2272
  exports.renderFrameToCanvas = renderFrameToCanvas;
2039
2273
  exports.renderGridBackground = renderGridBackground;
2274
+ exports.renderMorphBackground = renderMorphBackground;
2040
2275
  exports.renderNoiseBackground = renderNoiseBackground;
2041
2276
  exports.renderPulseBackground = renderPulseBackground;
2042
2277
  exports.renderRainBackground = renderRainBackground;
2278
+ exports.renderSilkBackground = renderSilkBackground;
2043
2279
  exports.renderStarsBackground = renderStarsBackground;
2280
+ exports.renderVoidBackground = renderVoidBackground;
2044
2281
  exports.renderWaveBackground = renderWaveBackground;
2045
2282
  exports.tryCreateWebGLRenderer = tryCreateWebGLRenderer;
2046
2283
  exports.videoToAsciiFrames = videoToAsciiFrames;