- 노드 반지름 4 → 6(고름 +2) · 노드 · 손잡이를 라벨 뒤 맨 위로
- 집기 문턱 노드 9 → 12 · pickAtScreen: 노드 가운데 6px 안 = 노드 · 밖 = 노드와 눈금 중 가까운 쪽
- stationAtScreen → {chainage, distance} · 맴돔은 집기와 같은 셈 · 노드 = 고리 · 눈금 = 파랑(새 _Hover)
- 누를 때 · 끄는 동안 · 재는 중 · 캔버스 밖 = 맴돔 끔 · [측점] 끔이면 눈금 안 봄
- 시험 test_b05_routeedit_pick 겹침 경우 · test_381_3_routeedit_node_pick
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
68 lines
2.7 KiB
TypeScript
68 lines
2.7 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_RouteEdit_Hover.ts
|
|
* 노선 편집 평면 **맴돔 밝힘**(요구 241-14 · PLAN 381-3).
|
|
*
|
|
* 맴도는 자리는 `_Pointer` 가 `_Input.pickAtScreen`(집기와 같은 셈)으로 적고, 여기서 이길 쪽만
|
|
* 그린다 — 노드 = 바깥 고리 · 횡단 눈금 = 파란 짧은 직각선. `_Render` 가 노드 그린 뒤 부름.
|
|
* ========================================================================== */
|
|
|
|
import { pickHover } from "./B05_Profile_UI_RouteEdit_Input";
|
|
import type { RouteEditScene } from "./B05_Profile_UI_RouteEdit_Render";
|
|
import { stationFrameAt } from "./logic/B05_Profile_UI_RouteEdit_Frame";
|
|
import type { Vertex } from "./logic/B05_Profile_UI_RouteEdit_Curve";
|
|
|
|
/** 횡단 눈금 맴돔 색 — 횡단 반폭 선(`_Render`)과 같은 하늘색. */
|
|
const STATION_HOVER_COLOR = "#0ea5e9";
|
|
|
|
/** 맴도는 자리 밝힘(381-3) — 누르면 집힐 쪽만: 노드 = 바깥 고리 · 횡단 눈금 = 파란 짧은 직각선. */
|
|
export function drawPickHover(
|
|
context: CanvasRenderingContext2D,
|
|
scene: RouteEditScene,
|
|
line: ReadonlyArray<Vertex>,
|
|
style: CSSStyleDeclaration,
|
|
nodeR: number,
|
|
): void {
|
|
const hover = pickHover(context.canvas);
|
|
if (!hover) return;
|
|
context.save();
|
|
context.setLineDash([]);
|
|
if ("node" in hover) {
|
|
const vertex = scene.planned[hover.node];
|
|
if (vertex) {
|
|
const [x, y] = scene.toScreen(vertex);
|
|
const radius = (hover.node === scene.picked ? nodeR + 2 : nodeR) + 4;
|
|
context.beginPath();
|
|
context.arc(x, y, radius, 0, Math.PI * 2);
|
|
context.strokeStyle = style.getPropertyValue("--map-halo") || "rgba(255,255,255,0.9)";
|
|
context.lineWidth = 4;
|
|
context.stroke();
|
|
context.strokeStyle = style.getPropertyValue("--map-route") || "#f97316";
|
|
context.lineWidth = 2;
|
|
context.stroke();
|
|
}
|
|
} else {
|
|
const frame = stationFrameAt(line, hover.chainage);
|
|
if (frame) {
|
|
const [ax, ay] = scene.toScreen(frame.origin);
|
|
const [bx, by] = scene.toScreen([
|
|
frame.origin[0] + frame.left[0],
|
|
frame.origin[1] + frame.left[1],
|
|
]);
|
|
const length = Math.hypot(bx - ax, by - ay) || 1;
|
|
const ux = ((bx - ax) / length) * 12;
|
|
const uy = ((by - ay) / length) * 12;
|
|
context.strokeStyle = STATION_HOVER_COLOR;
|
|
context.fillStyle = STATION_HOVER_COLOR;
|
|
context.lineWidth = 3;
|
|
context.beginPath();
|
|
context.moveTo(ax - ux, ay - uy);
|
|
context.lineTo(ax + ux, ay + uy);
|
|
context.stroke();
|
|
context.beginPath();
|
|
context.arc(ax, ay, 4, 0, Math.PI * 2);
|
|
context.fill();
|
|
}
|
|
}
|
|
context.restore();
|
|
}
|