统一组件图标布局并完善选择吸附交互

This commit is contained in:
ljz committed 2026-08-06 23:35:50 +08:00
1 parent 40c72422ff
commit 7671418582
16 files changed
+4359 -598

No files matched your search

+105 -43
View File
@@ -1,56 +1,76 @@
import {
SYMBOL_ACCENT,
SYMBOL_FILL,
SYMBOL_STROKE,
SymbolSvg,
} from "./primitives";
function ChamberCore({ variable }: { variable: boolean }) {
const PNCH012_STROKE = "#8b134f";
const PNCH_CHAMBER_CONTENT_SCALE = 0.45;
const PNCH_CHAMBER_CONTENT_CENTER = { x: 32, y: 24 } as const;
const PNCH_CHAMBER_CONTENT_TRANSFORM = `translate(${PNCH_CHAMBER_CONTENT_CENTER.x} ${PNCH_CHAMBER_CONTENT_CENTER.y}) scale(${PNCH_CHAMBER_CONTENT_SCALE}) translate(${-PNCH_CHAMBER_CONTENT_CENTER.x} ${-PNCH_CHAMBER_CONTENT_CENTER.y})`;
const PNCH_CHAMBER_LABEL_RENDERED_SIZE = 15;
const PNCH_CHAMBER_SMALL_CANVAS_SCALE = 96 / 64;
// SVG 字号使用 viewBox 逻辑单位;抵消 small 画布缩放后,工作区最终显示为 15px。
const PNCH_CHAMBER_LABEL_FONT_SIZE =
PNCH_CHAMBER_LABEL_RENDERED_SIZE / PNCH_CHAMBER_SMALL_CANVAS_SCALE;
function scalePnchChamberAnchor(x: number, y: number) {
return {
x:
PNCH_CHAMBER_CONTENT_CENTER.x +
(x - PNCH_CHAMBER_CONTENT_CENTER.x) * PNCH_CHAMBER_CONTENT_SCALE,
y:
PNCH_CHAMBER_CONTENT_CENTER.y +
(y - PNCH_CHAMBER_CONTENT_CENTER.y) * PNCH_CHAMBER_CONTENT_SCALE,
} as const;
}
export const PNCH012_PORT_ANCHORS = {
bottom: scalePnchChamberAnchor(32, 56),
left: scalePnchChamberAnchor(0, 24),
right: scalePnchChamberAnchor(64, 24),
top: scalePnchChamberAnchor(32, -8),
} as const;
export const PNCH023_PORT_ANCHORS = {
left: PNCH012_PORT_ANCHORS.left,
right: PNCH012_PORT_ANCHORS.right,
} as const;
export function AmesimPnch023Symbol() {
return (
<>
<circle
cx="32"
cy="24"
fill={SYMBOL_FILL}
r="13"
stroke={SYMBOL_STROKE}
strokeWidth="2"
/>
<SymbolSvg domain="pneumatic">
<g data-pnch023-part="symbol" transform={PNCH_CHAMBER_CONTENT_TRANSFORM}>
<path
d="M0 24H11M53 24H64"
data-pnch023-part="ports"
stroke={SYMBOL_STROKE}
strokeLinecap="butt"
strokeWidth="2"
/>
<circle
cx="32"
cy="24"
data-pnch023-part="chamber"
fill={SYMBOL_FILL}
r="21"
stroke={SYMBOL_STROKE}
strokeWidth="2"
/>
</g>
<text
data-pnch023-part="label"
dominantBaseline="central"
fill={SYMBOL_ACCENT}
fill={PNCH012_STROKE}
fontFamily="Arial, sans-serif"
fontSize="13"
fontWeight="700"
fontSize={PNCH_CHAMBER_LABEL_FONT_SIZE}
fontWeight="600"
textAnchor="middle"
x="32"
y="24"
>
Cp
</text>
{variable ? (
<g
fill="none"
stroke={SYMBOL_ACCENT}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
>
<path d="m20 13-5-5m0 0h4m-4 0v4" />
<path d="m44 13 5-5m0 0h-4m4 0v4" />
<path d="m20 35-5 5m0 0h4m-4 0v-4" />
<path d="m44 35 5 5m0 0h-4m4 0v-4" />
</g>
) : null}
</>
);
}
export function AmesimPnch023Symbol() {
return (
<SymbolSvg domain="pneumatic">
<path d="M2 24h17M45 24h17" stroke={SYMBOL_STROKE} strokeWidth="2" />
<ChamberCore variable={false} />
</SymbolSvg>
);
}
@@ -58,12 +78,54 @@ export function AmesimPnch023Symbol() {
export function AmesimPnch012Symbol() {
return (
<SymbolSvg domain="pneumatic">
<path
d="M2 16h17M2 32h17M45 16h17M45 32h17"
stroke={SYMBOL_STROKE}
strokeWidth="2"
/>
<ChamberCore variable />
<g data-pnch012-part="symbol" transform={PNCH_CHAMBER_CONTENT_TRANSFORM}>
<path
d="M0 24H11M53 24H64M32-8V3M32 45V56"
data-pnch012-part="ports"
stroke={PNCH012_STROKE}
strokeLinecap="butt"
strokeWidth="1.5"
/>
<circle
cx="32"
cy="24"
data-pnch012-part="chamber"
fill={SYMBOL_FILL}
r="21"
stroke={PNCH012_STROKE}
strokeWidth="1.5"
/>
<g
data-pnch012-part="volume-arrows"
fill="none"
stroke={PNCH012_STROKE}
strokeLinecap="butt"
strokeLinejoin="miter"
strokeWidth="1.5"
>
{[0, 90, 180, 270].map((rotation) => (
<path
d="M4-3 10 3M3 9H16V-4L3 9Z"
data-pnch012-part="volume-arrow"
key={rotation}
transform={`rotate(${rotation} 32 24)`}
/>
))}
</g>
</g>
<text
data-pnch012-part="label"
dominantBaseline="central"
fill={PNCH012_STROKE}
fontFamily="Arial, sans-serif"
fontSize={PNCH_CHAMBER_LABEL_FONT_SIZE}
fontWeight="600"
textAnchor="middle"
x="32"
y="24"
>
Cp
</text>
</SymbolSvg>
);
}