|
|
@@ -0,0 +1,50 @@
|
|
|
+// 相位方向箭头在"路口方块"内的几何布局
|
|
|
+// 共享于 SignalTimingChart (canvas 内绘图) 与 PhaseDiagram (CSS 布局)
|
|
|
+//
|
|
|
+// 坐标系: 30 × 30 单位的路口方块, 四角 + padX/padY + baseW/baseH
|
|
|
+// pos: LT / RT / LB / RB -- 哪个角落锚定
|
|
|
+// padX, padY: 离该角落的偏移 (与 pos 共同决定 anchor 边)
|
|
|
+// baseW, baseH: 箭头本身占的尺寸
|
|
|
+
|
|
|
+export const POS_MAP = {
|
|
|
+ // 1. 上方驶入 -> 靠左上角 (LT)
|
|
|
+ 'STRAIGHT_DOWN': { pos: 'LT', padX: 10, padY: 0, baseW: 7, baseH: 20.67 },
|
|
|
+ 'TURN_DOWN_LEFT': { pos: 'LT', padX: 10, padY: 0, baseW: 13, baseH: 21.33 },
|
|
|
+ 'TURN_DOWN_LEFT_UTURN': { pos: 'LT', padX: 10, padY: 0, baseW: 13, baseH: 22.67 },
|
|
|
+
|
|
|
+ // 2. 下方驶入 -> 靠右下角 (RB)
|
|
|
+ 'STRAIGHT_UP': { pos: 'RB', padX: 10, padY: 0, baseW: 7, baseH: 20.67 },
|
|
|
+ 'TURN_UP_LEFT': { pos: 'RB', padX: 10, padY: 0, baseW: 13, baseH: 21.33 },
|
|
|
+ 'TURN_UP_LEFT_UTURN': { pos: 'RB', padX: 10, padY: 0, baseW: 13, baseH: 22.67 },
|
|
|
+
|
|
|
+ // 3. 右侧驶入 -> 靠右上角 (RT)
|
|
|
+ 'STRAIGHT_LEFT': { pos: 'RT', padX: 0, padY: 10, baseW: 20.33, baseH: 6.33 },
|
|
|
+ 'TURN_LEFT_DOWN': { pos: 'RT', padX: 0, padY: 10, baseW: 20.67, baseH: 12.33 },
|
|
|
+ 'TURN_LEFT_DOWN_UTURN': { pos: 'RT', padX: 0, padY: 10, baseW: 22.67, baseH: 12.33 },
|
|
|
+
|
|
|
+ // 4. 左侧驶入 -> 靠左下角 (LB)
|
|
|
+ 'STRAIGHT_RIGHT': { pos: 'LB', padX: 0, padY: 10, baseW: 20.33, baseH: 6.33 },
|
|
|
+ 'TURN_RIGHT_UP': { pos: 'LB', padX: 0, padY: 10, baseW: 20.67, baseH: 12.33 },
|
|
|
+ 'TURN_RIGHT_UP_UTURN': { pos: 'LB', padX: 0, padY: 10, baseW: 22.67, baseH: 12.33 },
|
|
|
+};
|
|
|
+
|
|
|
+// 把 token 对应的 POS_MAP 项换算成 CSS 绝对定位 style (百分比, 自适应任意尺寸的方框)
|
|
|
+//
|
|
|
+// 两个独立缩放参数:
|
|
|
+// sizeScale - 作用于 baseW/baseH, 控制 "箭头本身大小" (1=原图, <1 变小, >1 变大)
|
|
|
+// padScale - 作用于 padX/padY, 控制 "离角偏移" (1=原图, <1 更靠角=中央留白大, >1 更靠中心)
|
|
|
+// 拆成两个是因为常见需求是"大小别动, 多腾点中央空间"。
|
|
|
+export function positionStyleOf(token, sizeScale = 1, padScale = 1) {
|
|
|
+ const m = POS_MAP[token];
|
|
|
+ if (!m) return {};
|
|
|
+ const sideX = m.pos === 'LT' || m.pos === 'LB' ? 'left' : 'right';
|
|
|
+ const sideY = m.pos === 'LT' || m.pos === 'RT' ? 'top' : 'bottom';
|
|
|
+ const pct = (n) => `${(n / 30) * 100}%`;
|
|
|
+ return {
|
|
|
+ position: 'absolute',
|
|
|
+ width: pct(m.baseW * sizeScale),
|
|
|
+ height: pct(m.baseH * sizeScale),
|
|
|
+ [sideX]: pct(m.padX * padScale),
|
|
|
+ [sideY]: pct(m.padY * padScale),
|
|
|
+ };
|
|
|
+}
|