feat(D03): 평면 도구줄을 공용 지도 도구줄로 — [?] 안내 · 측점 · 기울기 켬끔 더해 아홉 · 겹 단추 아이콘 (PLAN 568-3 · 569-2 · 요구 395)

- UI_Map — createMapTools · mapToolButton(되돌리기 · 다시하기 · 3D · 돌리기 둘 · 측점 · 기울기 · 거리 재기) · [?] 조작 안내 여덟 줄 · ScreenMap 에 측점 · 기울기 켬 실음
- UI_Draw — 측점 눈금 · 구간 길이 · 기울기 글을 켬끔 따라 그림
- UI_Layers — 겹 단추 글자 대신 공용 아이콘(satellite · droplet · borderAll · angle)
- test_553_4 — 옛 createToolbar · createIconButton 지킴을 공용 도구줄 · 겹 단추 지킴으로 바꿈

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 07:04:02 +09:00
co-authored by Claude Opus 5.5
parent 7f17af513c
commit b4e1b89943
5 changed files with 83 additions and 52 deletions
+40 -29
View File
@@ -1,7 +1,7 @@
/* =============================================================================
* D03_PlanAnalysis_UI_Map.ts
* D03 메인 평면(PLAN 530-3 · 562-3) — 위성 바탕 · 위에 겹(바탕 겹 569-2 · 그리기 · 거리재기) · 도구줄 여섯
* (되돌리기 · 다시하기 · 3D · 좌회전 · 우회전 · 거리재기).
* D03 메인 평면(PLAN 530-3 · 562-3) — 위성 바탕 · 위에 겹(바탕 겹 569-2 · 그리기 · 거리재기) · 도구줄 아홉
* (공용 `createMapTools` 568-3 — [?] · 되돌리기 · 다시하기 · 3D · 좌회전 · 우회전 · 측점 · 기울기 · 거리재기).
*
* 셈 · 그리기는 B 부품 그대로(import 만) — 좌표 `createMetricProjector` · `screenToMetric` · 맞춤
* `computeRouteView` · 휠 확대 · 가운데 단추 옮기기 `bindRouteEditNavigation` ·
@@ -10,9 +10,8 @@
* 겹은 돌리기 전 그림 좌표로 그리고 받음 — 누른 자리는 `unrotate` 로 되돌려 넘김.
* ========================================================================== */
import { createIconButton } from "@ui/ui_template_button";
import { createMapTools, mapToolButton } from "@ui/ui_template_map_tools";
import { themeColor } from "@ui/ui_template_palette";
import { createToolbar } from "@ui/ui_template_toolbar";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import {
computeMapRect,
@@ -56,6 +55,9 @@ export interface ScreenMap {
pxPerMeter: number;
/** B04 그리기 틀(`drawPreparedLayer` 등이 받음). */
view: ViewState;
/** 측점 눈금 · 구간 길이 · 기울기 글 켬(도구줄 측점 · 기울기). */
stations: boolean;
slopes: boolean;
/** 글자를 세울 각(라디안 · 안 돌렸으면 0). */
uprightRad: number;
/** (x, y) 둘레로 글자를 눈높이로 세워 그림(돌린 지도). */
@@ -129,36 +131,44 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
const root = document.createElement("div");
root.className = "d03-plan__map";
const canvas = document.createElement("canvas");
const tool = (
act: string,
icon: Parameters<typeof createIconButton>[0]["icon"],
title: string,
onClick?: () => void,
): HTMLButtonElement => {
const button = createIconButton({ icon, title, onClick });
button.dataset.act = act;
let marks = { stations: true, slopes: true };
const markButton = (act: "stations" | "slopes", title: string): HTMLButtonElement => {
const button = mapToolButton(act, {
title,
pressed: true,
onClick: () => {
marks = { ...marks, [act]: !marks[act] };
button.setAttribute("aria-pressed", String(marks[act]));
draw();
},
});
return button;
};
const undoButton = tool("undo", "undo", "되돌리기(Ctrl+Z)", events.onUndo);
const redoButton = tool("redo", "redo", "다시하기(Ctrl+Y)", events.onRedo);
const viewButton = tool("view3d", "cube", "3D 보기", events.on3d);
const measureButton = tool("measure", "ruler", "거리재기", events.onMeasure);
measureButton.setAttribute("aria-pressed", "false");
const toolbar = createToolbar({
glass: true,
size: 32,
const undoButton = mapToolButton("undo", { onClick: events.onUndo });
const redoButton = mapToolButton("redo", { onClick: events.onRedo });
const viewButton = mapToolButton("view3d", { onClick: events.on3d });
const measureButton = mapToolButton("measure", { onClick: events.onMeasure });
const tools = createMapTools({
label: "평면 도구",
items: [
undoButton,
redoButton,
"divider",
viewButton,
tool("rotate-ccw", "rotateCcw", "왼쪽으로 돌림(15°)"),
tool("rotate-cw", "rotateCw", "오른쪽으로 돌림(15°)"),
"divider",
measureButton,
hint: {
lines: [
"누름 = 점 찍기",
"Enter = 긋기 끝",
"Esc = 긋기 취소",
"Backspace = 마지막 점 빼기",
"오른쪽 누름 = 마크 지움",
"가운데 끌기 = 옮기기",
"휠 = 확대 · 축소",
"Ctrl+휠 = 돌리기",
],
},
groups: [
[undoButton, redoButton],
[viewButton, "rotate-ccw", "rotate-cw"],
[markButton("stations", "측점"), markButton("slopes", "구간 길이 · 기울기"), measureButton],
],
});
const toolbar = tools.root;
toolbar.classList.add("d03-plan__tools");
root.append(canvas, toolbar);
const context = canvas.getContext("2d")!;
@@ -187,6 +197,7 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
toMetric: (px, py) => screenToMetric(meta!, view, px, py),
pxPerMeter: projector.pxPerMeter,
view,
...marks,
uprightRad: rotation.uprightRad(),
upright: (ctx, x, y, paint) => {
const angle = rotation.uprightRad();