refactor(B04): 전처리 화면 자체 변종을 부품 상자 부품으로 — 켜기 칩 · 분할 고르기 · 고르기 · 슬라이더 · 값 목록 · 카드 · 도구줄 (PLAN 553-1)

- 지도 층 단추 열다섯 안팎 · 표시 토글 셋 · 라이다 겹침 = 켜기 칩(층 색 점) · 도엽 보간 방식 = 분할 고르기 · 도구줄 부품
- 고르기 38 → 고르기 부품 · 점 크기 · 밀도 = 슬라이더 · 입력 파일 정보 = 값 목록 · 초기화 = 위험 고스트 · 묶음 상자 = 카드 + 패널 머리
- 죽은 CSS 열여섯 걷음 · 날 색 → 공통 값 · 가이드 촬영 선택자 · 지킴 시험 test_553_1_pages 늘림

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 22:09:36 +09:00
co-authored by Claude Sonnet 5.5
parent a826804277
commit 58dafb1572
14 changed files with 441 additions and 858 deletions
+41 -51
View File
@@ -1,6 +1,8 @@
import { createButton } from "@ui/ui_template_elements";
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { wheelZoomsIn } from "../A00_Common/touch_bridge";
import { createProgressCircle } from "@ui/ui_template_progress";
import { createToolbar } from "@ui/ui_template_toolbar";
import {
fetchPlannedRoute,
fetchVWorldMeta,
@@ -23,6 +25,7 @@ import {
type GisLayer,
} from "./B04_PreProcess_UI_MapLayers";
import { createFlowStrengthOverlay } from "./B04_PreProcess_UI_FlowStrength";
import { createLayerToggle } from "./B04_PreProcess_UI_LayerToggle";
import { createWatershedOverlay } from "./B04_PreProcess_UI_Watershed";
import {
computeMapRect,
@@ -60,15 +63,16 @@ function L(key: keyof typeof ui_locales): string {
export function createSurfaceMapViewer(): SurfaceMapViewer {
const root = document.createElement("section");
root.className = "b04-map";
root.className = "ui-card b04-map";
root.dataset.pad = "16";
const header = document.createElement("div");
header.className = "b04-map__header";
const title = document.createElement("h3");
title.textContent = L("B04_Surface_Map_Title");
const controls = document.createElement("div");
controls.className = "b04-map__controls";
const controls = createToolbar({ items: [], size: 28 });
controls.classList.add("b04-map__controls");
const backgroundGroup = document.createElement("div");
backgroundGroup.className = "b04-map__control-group";
const backgroundTitle = document.createElement("span");
@@ -85,9 +89,11 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
gisButtons.className = "b04-map__layer-buttons";
gisGroup.append(gisTitle, gisButtons);
const resetButton = document.createElement("button");
resetButton.type = "button";
resetButton.textContent = L("B04_Surface_Map_Reset");
const resetButton = createButton({
label: L("B04_Surface_Map_Reset"),
variant: "ghost",
size: 28,
});
controls.append(backgroundGroup, gisGroup, resetButton);
header.append(title, controls);
@@ -188,25 +194,16 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
layer: T,
color?: string,
): HTMLButtonElement {
const button = document.createElement("button");
button.type = "button";
const initialActive = activeLayers.has(layer);
button.className = "b04-map__layer-button" + (initialActive ? " is-active" : "");
button.textContent = label;
button.setAttribute("aria-pressed", String(initialActive));
if (color) {
button.classList.add("b04-map__layer-button--gis");
button.style.setProperty("--b04-layer-color", color);
}
button.addEventListener("click", () => {
if (activeLayers.has(layer)) activeLayers.delete(layer);
else activeLayers.add(layer);
const isActive = activeLayers.has(layer);
button.classList.toggle("is-active", isActive);
button.setAttribute("aria-pressed", String(isActive));
syncLayerVisibility();
});
return button;
return createLayerToggle({
label,
color,
on: activeLayers.has(layer),
onChange: (on) => {
if (on) activeLayers.add(layer);
else activeLayers.delete(layer);
syncLayerVisibility();
},
}).root;
}
const backgroundLabels: Record<BackgroundLayer, string> = {
@@ -231,19 +228,16 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
};
// 계획선 토글 — 도엽 레이어와 같은 양식으로 레이어 줄 맨 앞에 둔다. 색은 B05 배수유역도와
// 같은 주황(정의처: MapRender). 계획노선을 아직 올리지 않았으면 버튼이 눌리지 않는다.
const routeButton = document.createElement("button");
routeButton.type = "button";
routeButton.className = "b04-map__layer-button b04-map__layer-button--gis is-active";
routeButton.textContent = L("B04_Surface_Map_PlannedRoute");
routeButton.style.setProperty("--b04-layer-color", routeLineColor());
routeButton.setAttribute("aria-pressed", "true");
routeButton.addEventListener("click", () => {
showRoute = !showRoute;
routeButton.classList.toggle("is-active", showRoute);
routeButton.setAttribute("aria-pressed", String(showRoute));
scheduleDraw();
const routeToggle = createLayerToggle({
label: L("B04_Surface_Map_PlannedRoute"),
color: routeLineColor(),
on: true,
onChange: (on) => {
showRoute = on;
scheduleDraw();
},
});
gisButtons.append(routeButton);
gisButtons.append(routeToggle.root);
GIS_LAYERS.forEach((layer) => {
gisButtons.append(
@@ -252,19 +246,15 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
});
// 등고 라벨 보기/숨기기 (등고선·도엽 등고선의 계곡선 수치 표기)
const contourLabelButton = document.createElement("button");
contourLabelButton.type = "button";
contourLabelButton.className =
"b04-map__layer-button" + (CONTOUR_LABEL_DEFAULT_ON ? " is-active" : "");
contourLabelButton.textContent = L("B04_Surface_Map_ContourLabel");
contourLabelButton.setAttribute("aria-pressed", String(CONTOUR_LABEL_DEFAULT_ON));
contourLabelButton.addEventListener("click", () => {
showContourLabels = !showContourLabels;
contourLabelButton.classList.toggle("is-active", showContourLabels);
contourLabelButton.setAttribute("aria-pressed", String(showContourLabels));
scheduleDraw();
const contourLabelToggle = createLayerToggle({
label: L("B04_Surface_Map_ContourLabel"),
on: CONTOUR_LABEL_DEFAULT_ON,
onChange: (on) => {
showContourLabels = on;
scheduleDraw();
},
});
gisButtons.append(contourLabelButton);
gisButtons.append(contourLabelToggle.root);
// 배수유역 분석 오버레이 — 계산은 백엔드가 하고 여기서는 겹쳐 그리기만 한다.
// 상태 문구는 오버레이 전용 줄에 쓴다 — 지도 자체 상태(레이어 로딩)와 같은 칸을 쓰면
@@ -505,8 +495,8 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
// 관 마커도 같은 계획선 위에 스냅한다 — 목록이 다르면 마커가 노선을 벗어난다.
detailBasins.setRoute(planned.points, nextMeta);
// 계획노선을 아직 올리지 않은 프로젝트에서는 켤 것이 없으니 버튼을 잠근다.
routeButton.disabled = routeLayer === null;
routeButton.title = routeLayer === null ? L("B04_Surface_Map_PlannedRouteEmpty") : "";
routeToggle.root.disabled = routeLayer === null;
routeToggle.root.title = routeLayer === null ? L("B04_Surface_Map_PlannedRouteEmpty") : "";
let featureCount = 0;
loadedLayers.forEach(([layer, data]) => {
if (!data) return;