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

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

+175 -73
View File
@@ -12,9 +12,63 @@ const MECHANICAL_LINE_WIDTH = 1.8;
const MECMAS21_STROKE = "#00af00";
const MECMAS21_HATCH = "#66cf66";
const MECMAS21_FILL = "#ffffff";
const MECMAS21_CONTENT_SCALE = 0.72;
const MECMAS21_CONTENT_CENTER = { x: 32, y: 24 } as const;
const MECMAS21_CONTENT_TRANSFORM = `translate(${MECMAS21_CONTENT_CENTER.x} ${MECMAS21_CONTENT_CENTER.y}) scale(${MECMAS21_CONTENT_SCALE}) translate(${-MECMAS21_CONTENT_CENTER.x} ${-MECMAS21_CONTENT_CENTER.y})`;
const MECMAS21_SELECTION_ENVELOPE = {
x: 9.608,
y: 2.328,
width: 44.784,
height: 43.344,
} as const;
const F000_CONTENT_SCALE = 0.25;
const F000_CONTENT_CENTER = { x: 32, y: 24 } as const;
const F000_CONTENT_TRANSFORM = `translate(${F000_CONTENT_CENTER.x} ${F000_CONTENT_CENTER.y}) scale(${F000_CONTENT_SCALE}) translate(${-F000_CONTENT_CENTER.x} ${-F000_CONTENT_CENTER.y})`;
const F000_FRAME_RIGHT_X =
F000_CONTENT_CENTER.x +
(52 - F000_CONTENT_CENTER.x) * F000_CONTENT_SCALE;
export const F000_PORT_ANCHOR = {
x: 48,
y: 24,
} as const;
const FORC_STROKE = "#00af00";
const FORC_CONTENT_SCALE = 0.64;
const FORC_CONTENT_CENTER = { x: 32, y: 24 } as const;
const FORC_CONTENT_TRANSFORM = `translate(${FORC_CONTENT_CENTER.x} ${FORC_CONTENT_CENTER.y}) scale(${FORC_CONTENT_SCALE}) translate(${-FORC_CONTENT_CENTER.x} ${-FORC_CONTENT_CENTER.y})`;
export const FORC_PORT_ANCHORS = {
left: {
x:
FORC_CONTENT_CENTER.x +
(2 - FORC_CONTENT_CENTER.x) * FORC_CONTENT_SCALE,
y: FORC_CONTENT_CENTER.y,
},
right: {
x:
FORC_CONTENT_CENTER.x +
(62 - FORC_CONTENT_CENTER.x) * FORC_CONTENT_SCALE,
y: FORC_CONTENT_CENTER.y,
},
} as const;
export const MECMAS21_PORT_ANCHORS = {
left: {
x:
MECMAS21_CONTENT_CENTER.x +
(2 - MECMAS21_CONTENT_CENTER.x) * MECMAS21_CONTENT_SCALE,
y: 24,
},
right: {
x:
MECMAS21_CONTENT_CENTER.x +
(62 - MECMAS21_CONTENT_CENTER.x) * MECMAS21_CONTENT_SCALE,
y: 24,
},
} as const;
const PNRP17_STROKE = "#8b134f";
const PNRP17_FILL = "#cf9db6";
const PNRP17_LIGHT_FILL = "#f5ebf0";
// PNRP17 使用最终像素线宽;几何缩放不再改变参考图中的粗细层级。
const PNRP17_PRIMARY_STROKE_WIDTH = 2;
const PNRP17_DETAIL_STROKE_WIDTH = 1.5;
const mechanicalStroke = {
fill: "none",
@@ -34,16 +88,16 @@ function MechanicalSocket({ side }: { side: "left" | "right" }) {
strokeLinejoin="miter"
>
<path
d={facingLeft ? "M2 24h3.2" : "M58.8 24H62"}
d={facingLeft ? "M2 24h4.2" : "M57.8 24H62"}
strokeWidth="0.9"
/>
<path
d={
facingLeft
? "M15.1 20.9H6.2v6.2h8.9"
: "M48.9 20.9h8.9v6.2h-8.9"
? "M14 18.5H6.2v11H14"
: "M50 18.5h7.8v11H50"
}
strokeWidth="2"
strokeWidth="2.5"
/>
</g>
);
@@ -52,18 +106,28 @@ function MechanicalSocket({ side }: { side: "left" | "right" }) {
export function AmesimF000Symbol() {
return (
<SymbolSvg className="component-symbol-amesim-f000" domain="mechanical">
<path d="M41 24h21" {...mechanicalStroke} />
<rect
fill={SYMBOL_FILL}
height="28"
rx="1"
stroke={SYMBOL_STROKE}
strokeWidth="2.2"
width="18"
x="23"
y="12"
/>
<path d="M27 26h10" stroke={SYMBOL_ACCENT} strokeWidth="2" />
<g data-f000-part="symbol">
<path
d={`M${F000_FRAME_RIGHT_X} ${F000_PORT_ANCHOR.y}H${F000_PORT_ANCHOR.x}`}
data-f000-part="extension"
stroke={SYMBOL_STROKE}
strokeLinecap="butt"
strokeWidth="1.5"
/>
<g data-f000-part="body" transform={F000_CONTENT_TRANSFORM}>
<rect
data-f000-part="frame"
fill="#ffffff"
height="34"
stroke={SYMBOL_STROKE}
strokeLinejoin="miter"
strokeWidth="2.5"
width="52"
x="0"
y="7"
/>
</g>
</g>
</SymbolSvg>
);
}
@@ -71,37 +135,64 @@ export function AmesimF000Symbol() {
export function AmesimForcSymbol() {
return (
<SymbolSvg className="component-symbol-amesim-forc" domain="mechanical">
<g
fill="none"
stroke={SYMBOL_ACCENT}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.8"
>
<path d="M2 24h15" />
<path d="m11 19 6 5-6 5" />
<g data-forc-part="symbol" transform={FORC_CONTENT_TRANSFORM}>
<path
d="M2 24H18"
data-forc-part="left-extension"
stroke={FORC_STROKE}
strokeLinecap="butt"
strokeWidth="1.5"
/>
<path
d="M11.5 19.8 18 24 11.5 28.2"
data-forc-part="input-arrow"
fill="none"
stroke={FORC_STROKE}
strokeLinecap="butt"
strokeLinejoin="miter"
strokeWidth="2"
/>
<rect
data-forc-part="mechanical-socket"
fill="#ffffff"
height="10"
stroke={FORC_STROKE}
strokeLinejoin="miter"
strokeWidth="2"
width="14"
x="39"
y="19"
/>
<path
d="M53 24H62"
data-forc-part="right-extension"
stroke={FORC_STROKE}
strokeLinecap="butt"
strokeWidth="1.5"
/>
<circle
cx="30"
cy="24"
data-forc-part="force-circle"
fill="#ffffff"
r="12"
stroke={FORC_STROKE}
strokeWidth="2"
/>
<text
data-forc-part="label"
dominantBaseline="central"
fill={FORC_STROKE}
fontFamily="Arial, sans-serif"
fontSize="15"
fontWeight="600"
textAnchor="middle"
x="30"
y="24"
>
F
</text>
</g>
<circle
cx="32"
cy="24"
fill={SYMBOL_FILL}
r="12"
stroke={SYMBOL_STROKE}
strokeWidth="2"
/>
<text
dominantBaseline="central"
fill={SYMBOL_STROKE}
fontFamily="Arial, sans-serif"
fontSize="13"
fontWeight="600"
textAnchor="middle"
x="32"
y="24"
>
F
</text>
<path d="M44 24h6M50 18v12M50 18h8M50 30h8M58 18v12M58 24h4" {...mechanicalStroke} />
</SymbolSvg>
);
}
@@ -141,7 +232,7 @@ export function AmesimMecmas21Symbol({
<path
d="M-1 1 1-1M0 5.05 5.05 0M4.05 6.05 6.05 4.05"
stroke={MECMAS21_HATCH}
strokeWidth="1.55"
strokeWidth="1"
/>
</pattern>
</defs>
@@ -149,23 +240,24 @@ export function AmesimMecmas21Symbol({
data-mecmas-friction={frictionEnabled ? "enabled" : "disabled"}
data-mecmas-limits={limitsEnabled ? "finite" : "unlimited"}
data-mecmas-variant={variant}
transform={MECMAS21_CONTENT_TRANSFORM}
>
{showGuides ? (
<g data-mecmas-part="guides">
<rect
data-mecmas-part="upper-guide"
fill={`url(#${hatchingId})`}
height="5.25"
height="8.5"
stroke={MECMAS21_STROKE}
strokeWidth="1.2"
width="60"
x="2"
y="2.6"
width="61"
x="1.5"
y="-5.5"
/>
{limitsEnabled ? (
<g data-mecmas-part="finite-lower-guide">
<path
d="M2 32.6H10V39.6H54V32.6H62V45.4H2Z"
d="M1.5 34.5H9V45H55V34.5H62.5V53.5H1.5Z"
fill={`url(#${hatchingId})`}
stroke={MECMAS21_STROKE}
strokeLinejoin="miter"
@@ -176,19 +268,19 @@ export function AmesimMecmas21Symbol({
<rect
data-mecmas-part="unlimited-lower-guide"
fill={`url(#${hatchingId})`}
height="5.25"
height="8.5"
stroke={MECMAS21_STROKE}
strokeWidth="1.2"
width="60"
x="2"
y="40.23"
width="61"
x="1.5"
y="45"
/>
)}
</g>
) : null}
{frictionEnabled ? (
<path
d="M16.49 9.93h4.9m3.81 0h4.9m3.93 0h4.9m3.79 0h4.9M16.49 38.07h4.9m3.81 0h4.9m3.93 0h4.9m3.79 0h4.9"
d="M16.5 5.25h4.9m3.8 0h4.9m3.9 0h4.9m3.8 0h4.9M16.5 42.75h4.9m3.8 0h4.9m3.9 0h4.9m3.8 0h4.9"
data-mecmas-part="friction-markers"
stroke={MECMAS21_STROKE}
strokeLinecap="butt"
@@ -201,12 +293,12 @@ export function AmesimMecmas21Symbol({
<rect
data-mecmas-part="mass"
fill={MECMAS21_FILL}
height="23.1"
height="34"
stroke={MECMAS21_STROKE}
strokeWidth="2"
width="34"
x="15"
y="12.45"
strokeWidth="2.5"
width="36"
x="14"
y="7"
/>
<text
dominantBaseline="central"
@@ -216,23 +308,33 @@ export function AmesimMecmas21Symbol({
fontWeight="500"
textAnchor="middle"
x="32"
y="29.2"
y="31"
>
M
</text>
<path
d="M18.94 18.8h5.88M21.9 16.6V21"
d="M18.8 16.8H25M21.9 13.8v6"
fill="none"
stroke={MECMAS21_STROKE}
strokeLinecap="square"
strokeWidth="1.05"
/>
<path
d="M45.92 18.81 39.66 15.31 39.54 17.98H26.55v1.74h12.99l.12 2.93Z"
d="M46 16.8 39.5 12v3.6h-13V18h13v3.6Z"
fill={MECMAS21_STROKE}
/>
</g>
</g>
{/* 固定选择包络:参数切换为仅中央滑块时,虚线框仍保持完整状态大小。 */}
<rect
data-mecmas-part="selection-envelope"
fill="transparent"
height={MECMAS21_SELECTION_ENVELOPE.height}
pointerEvents="none"
width={MECMAS21_SELECTION_ENVELOPE.width}
x={MECMAS21_SELECTION_ENVELOPE.x}
y={MECMAS21_SELECTION_ENVELOPE.y}
/>
</SymbolSvg>
);
}
@@ -322,27 +424,27 @@ export function AmesimPnrp17Symbol() {
fill={PNRP17_FILL}
stroke={PNRP17_STROKE}
strokeLinejoin="miter"
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
/>
<path
d="M8.2 26.7h12.7v13.8h2v6.7H8.2Z"
fill={PNRP17_FILL}
stroke={PNRP17_STROKE}
strokeLinejoin="miter"
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
/>
<path
d="M28 40.5h28.5v6.7H28Z"
fill={PNRP17_FILL}
stroke={PNRP17_STROKE}
strokeLinejoin="miter"
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
/>
<rect
fill={PNRP17_LIGHT_FILL}
height="34"
stroke={PNRP17_STROKE}
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
width="7.7"
x="40.8"
y="7.2"
@@ -352,7 +454,7 @@ export function AmesimPnrp17Symbol() {
fill={PNRP17_LIGHT_FILL}
height="2.8"
stroke={PNRP17_STROKE}
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
width="31.5"
x="9.3"
y="22.7"
@@ -361,7 +463,7 @@ export function AmesimPnrp17Symbol() {
fill={PNRP17_LIGHT_FILL}
height="2.8"
stroke={PNRP17_STROKE}
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
width="7.7"
x="47.8"
y="22.7"
@@ -370,7 +472,7 @@ export function AmesimPnrp17Symbol() {
d="M2 4.4h7.3m46.2 0H62M2 24.1h7.3m46.2 0H62M25.5 43.4V48"
stroke={PNRP17_STROKE}
strokeLinecap="butt"
strokeWidth="1.2"
strokeWidth={PNRP17_PRIMARY_STROKE_WIDTH}
/>
{[15.3, 33].map((centerY) => (
<g
@@ -379,7 +481,7 @@ export function AmesimPnrp17Symbol() {
stroke={PNRP17_STROKE}
strokeLinecap="butt"
strokeLinejoin="miter"
strokeWidth="1.1"
strokeWidth={PNRP17_DETAIL_STROKE_WIDTH}
>
<path d={`M28.8 ${centerY}h-3.4`} />
<path