@cardenelabs/cdl 0.73.0 → 0.75.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/CHANGELOG.md +76 -1
- package/dist/index.cjs +301 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +301 -196
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +361 -256
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +361 -256
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/kinds/shape-blockchain.tsx +129 -47
- package/src/kinds/shape-commerce.tsx +45 -14
- package/src/kinds/shape-finance.tsx +73 -19
- package/src/kinds/shape-people.tsx +3 -3
- package/src/kinds/shape-region.tsx +93 -1
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
shapeRegion,
|
|
4
|
+
labelPlan,
|
|
5
|
+
fitArt,
|
|
6
|
+
打ち消しの倍率,
|
|
7
|
+
type 打ち消す字,
|
|
8
|
+
} from "./shape-region";
|
|
3
9
|
import type { LaidNode } from "../types";
|
|
4
10
|
import { 字引きを作る, type CdlLang } from "../lang";
|
|
5
11
|
|
|
@@ -193,7 +199,7 @@ export function ShapeBankNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
193
199
|
})}
|
|
194
200
|
<path d={`M ${x - BANK_BODY_OUT} ${y + pedimentH} L ${r.cx} ${y - BANK_PEDIMENT_RISE} L ${x + bldW + BANK_BODY_OUT} ${y + pedimentH} Z`} fill="var(--cdl-node-fill, #ffffff)" stroke={frame.stroke} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
195
201
|
<circle cx={r.cx} cy={y + pedimentH / 2 + 4} r={14} fill="var(--cdl-tone-accent, #2d6a8f)" stroke={frame.stroke} strokeWidth={1.5} />
|
|
196
|
-
<text x={r.cx} y={y + pedimentH / 2 + 10} fontSize={18} fontWeight={700} textAnchor="middle" fill="#ffffff" fontFamily="Georgia, serif">
|
|
202
|
+
<text data-cdl-counter-scaled="0" x={r.cx} y={y + pedimentH / 2 + 10} fontSize={18} fontWeight={700} textAnchor="middle" fill="#ffffff" fontFamily="Georgia, serif">
|
|
197
203
|
$
|
|
198
204
|
</text>
|
|
199
205
|
<rect x={x - 4} y={y + pedimentH} width={bldW + 8} height={architraveH} fill="var(--cdl-divider, #d4d4d8)" fillOpacity={0.4} stroke={frame.stroke} strokeWidth={frame.strokeWidth} />
|
|
@@ -278,7 +284,7 @@ export function ShapeTrustBankNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
278
284
|
return <rect key={i} x={r.cx - w / 2} y={y + bldH + i * BANK_STEP_DY} width={w} height={BANK_STEP_H} fill="var(--cdl-divider, #d4d4d8)" fillOpacity={0.5 + i * 0.15} stroke={frame.stroke} strokeWidth={BANK_STEP_SW} />;
|
|
279
285
|
})}
|
|
280
286
|
<path d={`M ${x - 6} ${y + pedimentH} L ${r.cx} ${y + 2} L ${x + bldW + 6} ${y + pedimentH} Z`} fill="var(--cdl-node-fill, #ffffff)" stroke={frame.stroke} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
281
|
-
<text x={r.cx} y={y + pedimentH - 8} fontSize={15} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="var(--cdl-tone-accent, #2d6a8f)" fontFamily="Georgia, serif">
|
|
287
|
+
<text data-cdl-counter-scaled="0" x={r.cx} y={y + pedimentH - 8} fontSize={15} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="var(--cdl-tone-accent, #2d6a8f)" fontFamily="Georgia, serif">
|
|
282
288
|
{字引("trustBank.sign")}
|
|
283
289
|
</text>
|
|
284
290
|
<rect x={x - 4} y={y + pedimentH} width={bldW + 8} height={architraveH} fill="var(--cdl-divider, #d4d4d8)" fillOpacity={0.4} stroke={frame.stroke} strokeWidth={frame.strokeWidth} />
|
|
@@ -394,6 +400,11 @@ export function ShapeCreditCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
394
400
|
*/
|
|
395
401
|
const BROKERAGE_TICK_H = 12;
|
|
396
402
|
const BROKERAGE_LOGO_H = 26;
|
|
403
|
+
/** 電光掲示板の内側の帯と、そこに流れる相場の字の指定。 */
|
|
404
|
+
const BROKERAGE_TICK_INNER_H = 8;
|
|
405
|
+
const BROKERAGE_TICKER_SIZE = 5.5;
|
|
406
|
+
/** ロゴ帯の看板の字の指定。 */
|
|
407
|
+
const BROKERAGE_SIGN_SIZE = 12;
|
|
397
408
|
/** 窓の格子。 上端はロゴ帯の下、 下端は基壇の上。 */
|
|
398
409
|
const BROKERAGE_GRID_TOP = 62;
|
|
399
410
|
const BROKERAGE_CELL_W = 14;
|
|
@@ -454,7 +465,22 @@ export function ShapeBrokerageNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
454
465
|
);
|
|
455
466
|
const gridStartX = x + (w - (cols * cellW + (cols - 1) * gapX)) / 2;
|
|
456
467
|
const goldCells = new Set([`0,1`, `0,4`, `1,2`, `2,3`, `3,5`]); // ランダム点灯 window
|
|
457
|
-
|
|
468
|
+
/*
|
|
469
|
+
* 打ち消しの上限を出す帯 (#887)。 相場の字は電光掲示板の内側 (幅 w - 4、高さ 8) に入る。
|
|
470
|
+
*
|
|
471
|
+
* **看板 `$ SECURITIES` は打ち消さない**。 字間 2.5 を持ち幅が字数に比例するため、言語で
|
|
472
|
+
* 字数が変われば帯を超える (#886 の記号と同じ扱い)。
|
|
473
|
+
*/
|
|
474
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
475
|
+
{
|
|
476
|
+
text: 字引("brokerage.ticker"),
|
|
477
|
+
size: BROKERAGE_TICKER_SIZE,
|
|
478
|
+
帯: { 幅: w - 4, 高さ: BROKERAGE_TICK_INNER_H },
|
|
479
|
+
},
|
|
480
|
+
];
|
|
481
|
+
const 絵 = (倍率: number): JSX.Element => {
|
|
482
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
483
|
+
return (
|
|
458
484
|
<g>
|
|
459
485
|
{/* drop shadow */}
|
|
460
486
|
<ellipse cx={cx} cy={y + h + BROKERAGE_SHADOW_DY} rx={w * BROKERAGE_SHADOW_RX_RATIO} ry={BROKERAGE_SHADOW_RY} fill={frame.stroke} opacity={0.2} stroke="none" />
|
|
@@ -465,12 +491,12 @@ export function ShapeBrokerageNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
465
491
|
{/* 上部電光掲示板 tick */}
|
|
466
492
|
<rect x={x} y={y} width={w} height={BROKERAGE_TICK_H} fill="#0f1830" stroke="none" />
|
|
467
493
|
<rect x={x + 2} y={y + 2} width={w - 4} height={8} fill="#1a2340" stroke="none" />
|
|
468
|
-
<text x={cx} y={y + 9} fontSize={
|
|
494
|
+
<text data-cdl-counter-scaled="1" x={cx} y={y + 9} fontSize={BROKERAGE_TICKER_SIZE * 倍} fontWeight={700} textAnchor="middle" fill="#4ea36a" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
469
495
|
{字引("brokerage.ticker")}
|
|
470
496
|
</text>
|
|
471
497
|
{/* $ SECURITIES ロゴ帯 */}
|
|
472
498
|
<rect x={x} y={y + BROKERAGE_TICK_H} width={w} height={BROKERAGE_LOGO_H} fill="#e5c07b" stroke="none" />
|
|
473
|
-
<text x={cx} y={y + 30} fontSize={
|
|
499
|
+
<text data-cdl-counter-scaled="0" x={cx} y={y + 30} fontSize={BROKERAGE_SIGN_SIZE} fontWeight={700} letterSpacing={2.5} textAnchor="middle" fill="#0f1830">
|
|
474
500
|
{字引("brokerage.sign")}
|
|
475
501
|
</text>
|
|
476
502
|
{/* window grid (段数は高さ次第、 列は 6 固定) */}
|
|
@@ -492,7 +518,8 @@ export function ShapeBrokerageNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
492
518
|
{/* 底部床 (ATM のように狭め) */}
|
|
493
519
|
<rect x={x - BROKERAGE_FLOOR_OUT} y={y + h + BROKERAGE_FLOOR_DY} width={w + BROKERAGE_FLOOR_OUT * 2} height={BROKERAGE_FLOOR_H} fill="#5a6270" stroke="none" />
|
|
494
520
|
</g>
|
|
495
|
-
|
|
521
|
+
);
|
|
522
|
+
};
|
|
496
523
|
return (
|
|
497
524
|
<g>
|
|
498
525
|
{fitArt(r, 広がり, 絵)}
|
|
@@ -502,6 +529,9 @@ export function ShapeBrokerageNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
502
529
|
}
|
|
503
530
|
|
|
504
531
|
/** shape-exchange = E2-A 中央 clearing house (hexagon EXCHANGE + 放射 8 node + 双方向 tx dots) */
|
|
532
|
+
/** 六角形の下に置く清算の字の指定。 */
|
|
533
|
+
const EXCHANGE_SUB_SIZE = 8;
|
|
534
|
+
|
|
505
535
|
export function ShapeExchangeNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
506
536
|
const 字引 = 字引きを作る(lang);
|
|
507
537
|
const frame = commonFrame(active);
|
|
@@ -540,7 +570,7 @@ export function ShapeExchangeNode({ node, active, lang }: ShapeProps): JSX.Eleme
|
|
|
540
570
|
*/
|
|
541
571
|
const 節点 = Math.max(0, nodeR) + 8 + 1.5 / 2;
|
|
542
572
|
const 六角 = hexR + frame.strokeWidth / 2;
|
|
543
|
-
const 字下 = 26 +
|
|
573
|
+
const 字下 = 26 + EXCHANGE_SUB_SIZE * 0.25;
|
|
544
574
|
const 外 = Math.max(節点, 六角);
|
|
545
575
|
const ずれ = cy - r.cy;
|
|
546
576
|
const 広がり = {
|
|
@@ -549,7 +579,19 @@ export function ShapeExchangeNode({ node, active, lang }: ShapeProps): JSX.Eleme
|
|
|
549
579
|
左: 外,
|
|
550
580
|
右: 外,
|
|
551
581
|
};
|
|
552
|
-
|
|
582
|
+
/*
|
|
583
|
+
* 打ち消しの上限を出す帯 (#887)。 清算の字は六角形の下の空いた所に置くので、幅は絵の横幅を
|
|
584
|
+
* そのまま使える。 高さは字の下の余り (`字下`) に合わせて 14 を採る。
|
|
585
|
+
*
|
|
586
|
+
* **看板 `EXCHANGE` と記号 `⇄` は打ち消さない**。 前者は字間 2 を持ち幅が字数に比例し、
|
|
587
|
+
* 後者は六角形の中に余白を持たない。
|
|
588
|
+
*/
|
|
589
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
590
|
+
{ text: 字引("exchange.sub"), size: EXCHANGE_SUB_SIZE, 帯: { 幅: 外 * 2, 高さ: 14 } },
|
|
591
|
+
];
|
|
592
|
+
const 絵 = (倍率: number): JSX.Element => {
|
|
593
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
594
|
+
return (
|
|
553
595
|
<g>
|
|
554
596
|
{/* 8 dashed radial lines */}
|
|
555
597
|
{nodes.map((n, i) => (
|
|
@@ -567,17 +609,18 @@ export function ShapeExchangeNode({ node, active, lang }: ShapeProps): JSX.Eleme
|
|
|
567
609
|
})}
|
|
568
610
|
{/* 中央 hexagon EXCHANGE (単色 #255a7a、 縦向き正六角形) */}
|
|
569
611
|
<path d={hexPath} fill="#255a7a" stroke={accentDarker} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
570
|
-
<text x={cx} y={cy - 8} fontSize={10} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("exchange.sign")}</text>
|
|
612
|
+
<text data-cdl-counter-scaled="0" x={cx} y={cy - 8} fontSize={10} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("exchange.sign")}</text>
|
|
571
613
|
{/* swap 記号 */}
|
|
572
|
-
<text data-cdl-role="node-body" x={cx} y={cy + 12} fontSize={22} fontWeight={700} textAnchor="middle" fill="#e5c07b">⇄</text>
|
|
614
|
+
<text data-cdl-counter-scaled="0" data-cdl-role="node-body" x={cx} y={cy + 12} fontSize={22} fontWeight={700} textAnchor="middle" fill="#e5c07b">⇄</text>
|
|
573
615
|
{/* clearing label */}
|
|
574
|
-
<text x={cx} y={cy + 26} fontSize={
|
|
616
|
+
<text data-cdl-counter-scaled="1" x={cx} y={cy + 26} fontSize={EXCHANGE_SUB_SIZE * 倍} fontWeight={700} textAnchor="middle" fill="#a4b5f2">{字引("exchange.sub")}</text>
|
|
575
617
|
{/* 8 外周 node (buyer/seller) */}
|
|
576
618
|
{nodes.map((n, i) => (
|
|
577
619
|
<circle key={`n${i}`} cx={n.cx} cy={n.cy} r={8} fill={n.fill} stroke={accentDarker} strokeWidth={1.5} />
|
|
578
620
|
))}
|
|
579
621
|
</g>
|
|
580
|
-
|
|
622
|
+
);
|
|
623
|
+
};
|
|
581
624
|
return (
|
|
582
625
|
<g>
|
|
583
626
|
{fitArt(r, 広がり, 絵)}
|
|
@@ -654,21 +697,32 @@ export function ShapeAtmNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
|
654
697
|
// 画面と 10 キーが潰れて読めなくなる
|
|
655
698
|
const 面 = Math.min(1, atmW / ATM_PANEL_W, atmH / ATM_PANEL_H);
|
|
656
699
|
const 面左 = -ATM_PANEL_W / 2;
|
|
700
|
+
/*
|
|
701
|
+
* **操作面の字は打ち消さない** (#887)。 画面は高さ 52 に 3 行 (指定 10 / 8 / 10) を詰めており、
|
|
702
|
+
* 行の間隔が 12 から 14 しか無い = 指定 10 の字に対して行の間隔の 8 割を割る
|
|
703
|
+
* (12 * 0.8 / 10 = 0.96)。 打ち消すと上下の行か画面の枠に触れる。
|
|
704
|
+
*
|
|
705
|
+
* 1 行だけ除いて残りを戻す形も採らない = 画面の 3 行は 1 つのまとまりなので、`¥ 20,000` だけ
|
|
706
|
+
* 戻さないと金額が見出しより小さくなる。 鍵盤の数字 (18x10 の鍵に入る絵) と天井看板
|
|
707
|
+
* (字間 2 を持ち幅が字数に比例する) も据え置く。
|
|
708
|
+
*
|
|
709
|
+
* 縮む前から画面の字が読める大きさに届かないこと自体は別の課題 (cardene777/cdl#888)。
|
|
710
|
+
*/
|
|
657
711
|
const 絵 = (
|
|
658
712
|
<g>
|
|
659
713
|
{/* drop shadow */}
|
|
660
714
|
<ellipse cx={cx} cy={y + totalH + ATM_SHADOW_DY} rx={totalW * ATM_SHADOW_RX_RATIO} ry={ATM_SHADOW_RY} fill={frame.stroke} opacity={0.15} stroke="none" />
|
|
661
715
|
{/* 天井 ATM CORNER 看板 */}
|
|
662
716
|
<rect x={centerX - totalW / 2} y={signY} width={totalW} height={signH} fill={accentDarker} stroke="#000" strokeWidth={ATM_SIGN_SW} />
|
|
663
|
-
<text x={centerX} y={signY + 17} fontSize={11} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("atm.sign")}</text>
|
|
717
|
+
<text data-cdl-counter-scaled="0" x={centerX} y={signY + 17} fontSize={11} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("atm.sign")}</text>
|
|
664
718
|
{/* ATM body */}
|
|
665
719
|
<rect data-cdl-role="node-body" x={atmX} y={atmY} width={atmW} height={atmH} rx={6} fill="#255a7a" stroke={accentDarker} strokeWidth={frame.strokeWidth} />
|
|
666
720
|
<g transform={`translate(${centerX} ${atmY}) scale(${面})`}>
|
|
667
721
|
{/* screen */}
|
|
668
722
|
<rect x={面左 + 8} y={10} width={ATM_PANEL_W - 16} height={52} rx={3} fill="#0f1830" stroke="#000" strokeWidth={1.5} />
|
|
669
|
-
<text x={0} y={30} fontSize={10} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">お引出し</text>
|
|
670
|
-
<text x={0} y={44} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">{字引("atm.screen")}</text>
|
|
671
|
-
<text x={0} y={56} fontSize={10} fontWeight={700} textAnchor="middle" fill="#4ea36a">¥ 20,000</text>
|
|
723
|
+
<text data-cdl-counter-scaled="0" x={0} y={30} fontSize={10} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">お引出し</text>
|
|
724
|
+
<text data-cdl-counter-scaled="0" x={0} y={44} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">{字引("atm.screen")}</text>
|
|
725
|
+
<text data-cdl-counter-scaled="0" x={0} y={56} fontSize={10} fontWeight={700} textAnchor="middle" fill="#4ea36a">¥ 20,000</text>
|
|
672
726
|
{/* keypad 5x2 */}
|
|
673
727
|
<rect x={面左 + 8} y={68} width={ATM_PANEL_W - 16} height={42} rx={2} fill="#8b949e" stroke="#5a6270" strokeWidth={1} />
|
|
674
728
|
{(() => {
|
|
@@ -688,7 +742,7 @@ export function ShapeAtmNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
|
688
742
|
return (
|
|
689
743
|
<g key={`k${i}`}>
|
|
690
744
|
<rect x={kx} y={ky} width={keyW} height={keyH} fill={k[1]} stroke="#0f1830" strokeWidth={0.8} />
|
|
691
|
-
<text x={kx + keyW / 2} y={ky + 7} fontSize={/* 決める鍵 (末尾) は 2 字あるので小さく描く。 字は言語で変わるため位置で見分ける */ i === keys.length - 1 ? 6 : 7} fontWeight={700} textAnchor="middle" fill="#ffffff">{k[0]}</text>
|
|
745
|
+
<text data-cdl-counter-scaled="0" x={kx + keyW / 2} y={ky + 7} fontSize={/* 決める鍵 (末尾) は 2 字あるので小さく描く。 字は言語で変わるため位置で見分ける */ i === keys.length - 1 ? 6 : 7} fontWeight={700} textAnchor="middle" fill="#ffffff">{k[0]}</text>
|
|
692
746
|
</g>
|
|
693
747
|
);
|
|
694
748
|
});
|
|
@@ -696,7 +750,7 @@ export function ShapeAtmNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
|
696
750
|
{/* card slot */}
|
|
697
751
|
<rect x={面左 + 12} y={116} width={ATM_PANEL_W - 24} height={8} rx={1.5} fill="#0f1830" stroke={accentDarker} strokeWidth={1} />
|
|
698
752
|
<rect x={面左 + 15} y={118} width={ATM_PANEL_W - 30} height={4} rx={0.5} fill="#e5c07b" />
|
|
699
|
-
<text x={0} y={132} fontSize={6} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">{字引("atm.cardSlot")}</text>
|
|
753
|
+
<text data-cdl-counter-scaled="0" x={0} y={132} fontSize={6} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">{字引("atm.cardSlot")}</text>
|
|
700
754
|
{/* cash slot */}
|
|
701
755
|
<rect x={面左 + 12} y={136} width={ATM_PANEL_W - 24} height={4} rx={1} fill="#0f1830" />
|
|
702
756
|
</g>
|
|
@@ -334,7 +334,7 @@ export function ShapeNotaryNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
334
334
|
<line x1={chestX - 14} y1={chestY + 14} x2={chestX + 14} y2={chestY + 14} stroke="#8b949e" strokeWidth={1} />
|
|
335
335
|
<line x1={chestX - 14} y1={chestY + 22} x2={chestX + 8} y2={chestY + 22} stroke="#8b949e" strokeWidth={1} />
|
|
336
336
|
<line x1={chestX - 14} y1={chestY + 34} x2={chestX + 2} y2={chestY + 34} stroke="#0f3450" strokeWidth={1.5} />
|
|
337
|
-
<text x={chestX + 6} y={chestY + 37} fontSize={8} fill="#0f3450" fontFamily="cursive" fontStyle="italic">
|
|
337
|
+
<text data-cdl-counter-scaled="0" x={chestX + 6} y={chestY + 37} fontSize={8} fill="#0f3450" fontFamily="cursive" fontStyle="italic">
|
|
338
338
|
✓
|
|
339
339
|
</text>
|
|
340
340
|
{/* 右下 印章 badge */}
|
|
@@ -342,7 +342,7 @@ export function ShapeNotaryNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
342
342
|
<g>
|
|
343
343
|
<circle cx={0} cy={0} r={12} fill="#c15a4a" stroke="none" />
|
|
344
344
|
<circle cx={0} cy={0} r={8} fill="none" stroke="#ffffff" strokeWidth={1.2} />
|
|
345
|
-
<text x={0} y={4} fontFamily="Georgia, serif" fontSize={10} fontWeight={700} fill="#ffffff" textAnchor="middle">
|
|
345
|
+
<text data-cdl-counter-scaled="0" x={0} y={4} fontFamily="Georgia, serif" fontSize={10} fontWeight={700} fill="#ffffff" textAnchor="middle">
|
|
346
346
|
印
|
|
347
347
|
</text>
|
|
348
348
|
</g>
|
|
@@ -420,7 +420,7 @@ export function ShapeCustomerServiceNode({ node, active }: ShapeProps): JSX.Elem
|
|
|
420
420
|
{collarV(cx, cy, p.strokeColor)}
|
|
421
421
|
{/* 体内 24H badge */}
|
|
422
422
|
<rect x={chestX - 22} y={chestY + 5} width={44} height={22} rx={11} fill="#e5c07b" stroke="#a67c00" strokeWidth={2} />
|
|
423
|
-
<text x={chestX} y={chestY + 20} fontSize={12} fontWeight={900} fill="#5a3a10" textAnchor="middle" letterSpacing={2}>
|
|
423
|
+
<text data-cdl-counter-scaled="0" x={chestX} y={chestY + 20} fontSize={12} fontWeight={900} fill="#5a3a10" textAnchor="middle" letterSpacing={2}>
|
|
424
424
|
24H
|
|
425
425
|
</text>
|
|
426
426
|
{/* 右下 headset badge */}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import type { JSX } from "react";
|
|
23
23
|
import type { LaidNode, NodeKind } from "../types";
|
|
24
|
+
import { MONO_ADVANCE_RATIO, displayWidth } from "./row-align";
|
|
25
|
+
import { textWidth } from "./text-width";
|
|
24
26
|
|
|
25
27
|
// 既存の呼出 (検査を含む) がここから取っているため、 そのまま出し直す。
|
|
26
28
|
export { textWidth } from "./text-width";
|
|
@@ -508,8 +510,98 @@ export function fitArt(
|
|
|
508
510
|
// 書くと変換の形が 2 通りになり、 読む側が両方を扱う必要が出る (実測 = 検査の変換 parser が
|
|
509
511
|
// `translate(0 1)` を読めず 8 件落ちた)。 `scale(1)` は無害なので形を 1 つに保つ
|
|
510
512
|
return (
|
|
511
|
-
|
|
513
|
+
/*
|
|
514
|
+
* 包みに印を付ける (#886)。 **`scale(` を持つ変換は他にもある** = `event` は目立たせる
|
|
515
|
+
* ための脈動を `scale(0.78)` から `scale(1)` で描き、絵を箱に収める縮小ではない。
|
|
516
|
+
* 祖先の変換を正規表現で見る形だと、その脈動まで「絵の縮小」 として数える。
|
|
517
|
+
*/
|
|
518
|
+
<g data-cdl-art-fit="1" transform={`translate(${dx} ${dy}) scale(${s})`}>
|
|
512
519
|
{組む(s)}
|
|
513
520
|
</g>
|
|
514
521
|
);
|
|
515
522
|
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* 打ち消しを掛ける字 1 つ (#886)。
|
|
526
|
+
*
|
|
527
|
+
* `帯` はその字が座る場所の広さ (絵の座標)。 行なら行の間隔と行の内側の幅、
|
|
528
|
+
* 見出しなら見出しの帯の高さと、見出しが使える幅。
|
|
529
|
+
*
|
|
530
|
+
* **絵が自分の定数から渡す**。 表に書き写すと、絵の寸法を変えた日に片方だけ古くなる
|
|
531
|
+
* (`ArtExtent` と同じ考え方)。
|
|
532
|
+
*/
|
|
533
|
+
export type 打ち消す字 = {
|
|
534
|
+
/** 描く字。 幅の上限を出すのに使う */
|
|
535
|
+
text: string;
|
|
536
|
+
/** 打ち消す前の指定 */
|
|
537
|
+
size: number;
|
|
538
|
+
/** 字間。 渡さない呼び方は 0 */
|
|
539
|
+
letterSpacing?: number;
|
|
540
|
+
/** その字が座る場所の広さ */
|
|
541
|
+
帯: { 幅: number; 高さ: number };
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* 打ち消した字が帯の高さのどこまでを占めてよいか。 超えると隣の行や帯の縁に触れる。
|
|
546
|
+
*
|
|
547
|
+
* **高さにだけ掛ける**。 帯の高さは行の間隔 = 次の行までの距離なので、字がそのまま使うと
|
|
548
|
+
* 上下が触れる。 帯の幅は絵が余白を引いた内側の幅を渡すので、そのまま使ってよい
|
|
549
|
+
* (8 割で止めると、字を切る予算より狭い所で打ち消しが止まって 2 割を捨てる)。
|
|
550
|
+
*/
|
|
551
|
+
const 帯の高さに対する上限 = 0.8;
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* 絵の中の字の幅。 **実物以上に出る側へ倒す**。
|
|
555
|
+
*
|
|
556
|
+
* 等幅の字送りで数えた値と、字形から数えた値の大きい方を採る = 下回ると
|
|
557
|
+
* 「収まっていない物を収まっていると判定」 する向きに外れる (`row-align.ts` の
|
|
558
|
+
* `rowColumnWidth` と同じ考え方)。
|
|
559
|
+
*/
|
|
560
|
+
export function 絵の中の字の幅(text: string, size: number, letterSpacing = 0): number {
|
|
561
|
+
return Math.max(
|
|
562
|
+
displayWidth(text) * size * MONO_ADVANCE_RATIO,
|
|
563
|
+
textWidth(text, size, letterSpacing),
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* 縮んだ分を字の指定で打ち消す倍率 (#871 で連鎖の箱に入れ、#886 で共通化した)。
|
|
569
|
+
*
|
|
570
|
+
* 入れ子の絵は決まった大きさで組んでから `fitArt` が箱に収まる倍率で丸ごと縮めるため、
|
|
571
|
+
* 字も一緒に縮む (実測 = 指定 10.5 が倍率 0.719 の図で 7.55)。 字の指定にこの倍率を掛けると
|
|
572
|
+
* 画面に出る大きさが指定へ戻る。
|
|
573
|
+
*
|
|
574
|
+
* ## 上限は絵の中の帯から出す
|
|
575
|
+
*
|
|
576
|
+
* 固定値にすると、絵の寸法を変えた日に効き方だけが変わる。
|
|
577
|
+
* **幅と高さの両方から出して小さい方を採る** (#886) = 高さだけで止めると、中央揃えの看板の
|
|
578
|
+
* ように幅が字数に比例して伸びる字が横へ出る。
|
|
579
|
+
*
|
|
580
|
+
* ## 帯に収まっていない字では打ち消さない
|
|
581
|
+
*
|
|
582
|
+
* 上限が 1 を下回る字がある絵では 1 を返す (実測 = 判子の中の `印` は半径 8 の丸に収まる
|
|
583
|
+
* 四角の 1 辺 11.3 を指定 10 の 1 字でほぼ使い切っており、幅から出る上限は 1 を下回る)。
|
|
584
|
+
* 打ち消す側に倒すと、その字が確実に入れ物から出る。
|
|
585
|
+
*
|
|
586
|
+
* ## 測れる字が 1 つも無い時も打ち消さない
|
|
587
|
+
*
|
|
588
|
+
* 帯の値が有限の正の値でない絵は、収まるかの判定ができない。
|
|
589
|
+
* `fitArt` が判定できない入力で手を触れないのと同じ向きに倒す。
|
|
590
|
+
*/
|
|
591
|
+
export function 打ち消しの倍率(倍率: number, 字ら: readonly 打ち消す字[]): number {
|
|
592
|
+
const 戻し = Number.isFinite(倍率) && 倍率 > 0 ? 1 / 倍率 : 1;
|
|
593
|
+
let 上限 = Number.POSITIVE_INFINITY;
|
|
594
|
+
for (const 字 of 字ら) {
|
|
595
|
+
if (!(Number.isFinite(字.size) && 字.size > 0)) continue;
|
|
596
|
+
const { 幅, 高さ } = 字.帯;
|
|
597
|
+
if (Number.isFinite(高さ) && 高さ > 0) {
|
|
598
|
+
上限 = Math.min(上限, (高さ * 帯の高さに対する上限) / 字.size);
|
|
599
|
+
}
|
|
600
|
+
const 実幅 = 絵の中の字の幅(字.text, 字.size, 字.letterSpacing ?? 0);
|
|
601
|
+
if (Number.isFinite(幅) && 幅 > 0 && 実幅 > 0) {
|
|
602
|
+
上限 = Math.min(上限, 幅 / 実幅);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
if (!Number.isFinite(上限)) return 1;
|
|
606
|
+
return Math.max(1, Math.min(戻し, 上限));
|
|
607
|
+
}
|