feat(B04): 배수유역 진행 문구를 지도 우상단 전용 줄로 분리

한 줄을 결과와 같이 쓰다 보니 분석을 돌릴 때마다 직전 결과가 지워졌다. 진행 문구는
우상단, 결과는 좌상단에 남겨 둘 다 동시에 읽을 수 있게 했다(2026-08-01 사용자 지시).

- WatershedOverlay에 busyElement(진행 전용)를 추가하고 sayBusy()로 갱신한다.
  결과·오류는 종전대로 statusElement(좌상단)에 쓴다.
- 분석이 끝나면 진행 문구를 거둔다.
- 지도에 .b04-map__status-topright 자리를 신설했다. 객체 개수는 우하단
  (.b04-map__status-corner), 유역 결과·흐름 강도 요약은 좌상단 그대로다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-01 16:57:16 +09:00
co-authored by Claude Opus 5
parent d5d97547f5
commit 2375a2f3ba
3 changed files with 40 additions and 2 deletions
@@ -169,6 +169,10 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
const statusCorner = document.createElement("div");
statusCorner.className = "b04-map__status-corner";
statusCorner.append(status);
// 우측 최상단 — 배수유역 "분석 중…" 진행 문구 자리(2026-08-01 사용자 지시).
// 좌상단 결과 줄을 지우지 않도록 자리를 따로 준다.
const statusTopRight = document.createElement("div");
statusTopRight.className = "b04-map__status-topright";
const scaleBar = document.createElement("div");
scaleBar.className = "b04-map__scale";
const scaleText = document.createElement("span");
@@ -181,6 +185,7 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
canvas,
empty,
statusStack,
statusTopRight,
statusCorner,
scaleBar,
progress.root,
@@ -341,6 +346,7 @@ export function createSurfaceMapViewer(): SurfaceMapViewer {
controls.insertBefore(watershedGroup, resetButton);
// 안내·결과 문구는 컨트롤 줄이 아니라 지도 위에 얹는다 — 컨트롤 영역 세로 공간을 먹지 않는다.
statusStack.append(watershed.statusElement, flowStatus);
statusTopRight.append(watershed.busyElement);
function updateImageTransform(): void {
backgroundImages.forEach((image) => {
@@ -681,6 +681,21 @@
pointer-events: none;
}
/* 배수유역 "분석 중…" 진행 문구 자리 — 우측 최상단(2026-08-01 사용자 지시).
결과 문구는 좌상단에 그대로 남는다. */
.b04-map__status-topright {
position: absolute;
z-index: 2;
top: var(--spacing-12);
right: var(--spacing-12);
display: flex;
max-width: min(40%, 360px);
flex-direction: column;
align-items: flex-end;
gap: var(--spacing-4);
pointer-events: none;
}
/* 객체 표시(지형지물 개수) 라벨 자리 — 우측 최하단(2026-08-01 사용자 지시).
축척은 좌하단이라 서로 겹치지 않는다. */
.b04-map__status-corner {
@@ -79,8 +79,10 @@ export interface WatershedOverlay {
button: HTMLButtonElement;
/** 갈래별 표시 토글 버튼(1차 유역 / 2차 유역 / 유역 방향 / 평균 흐름). */
partButtons: HTMLButtonElement[];
/** 배수유역 전용 상태 줄. 지도 자체 상태(레이어 로딩 등)와 섞이면 서로 덮어쓴다. */
/** 배수유역 **결과** 줄(좌상단). 지도 자체 상태(레이어 로딩 등)와 섞이면 서로 덮어쓴다. */
statusElement: HTMLElement;
/** 분석 **진행 중** 줄(우상단). 결과를 지우지 않고 따로 뜬다. */
busyElement: HTMLElement;
/** 켜져 있는지. draw() 호출 전에 확인한다. */
visible: () => boolean;
/** 상태 문구(분석 요약 또는 오류). 없으면 빈 문자열. */
@@ -105,6 +107,12 @@ export function createWatershedOverlay(onChange: () => void): WatershedOverlay {
statusElement.className = "b04-map__watershed-status";
statusElement.hidden = true;
// 진행 문구는 결과 문구와 자리를 나눈다 — 결과는 좌상단에 남겨 두고 "분석 중…"만 우상단에
// 띄운다(2026-08-01 사용자 지시). 한 줄을 같이 쓰면 분석을 돌릴 때마다 직전 결과가 지워진다.
const busyElement = document.createElement("span");
busyElement.className = "b04-map__watershed-status";
busyElement.hidden = true;
/** 상태 줄을 갱신한다. 빈 문자열이면 줄 자체를 숨긴다. */
function say(text: string): void {
statusText = text;
@@ -112,6 +120,12 @@ export function createWatershedOverlay(onChange: () => void): WatershedOverlay {
statusElement.hidden = text === "";
}
/** 진행 중 문구(우상단). 빈 문자열이면 감춘다. */
function sayBusy(text: string): void {
busyElement.textContent = text;
busyElement.hidden = text === "";
}
const button = document.createElement("button");
button.type = "button";
button.className = "b04-map__layer-button b04-map__layer-button--gis";
@@ -483,7 +497,8 @@ export function createWatershedOverlay(onChange: () => void): WatershedOverlay {
button.textContent = L(
refresh ? "B04_Surface_Watershed_Btn_Analyzing" : "B04_Surface_Watershed_Btn_Loading",
);
say(
// 진행 문구는 우상단 전용 줄에 띄운다 — 좌상단의 직전 결과를 지우지 않는다.
sayBusy(
L(
refresh ? "B04_Surface_Watershed_Status_Analyzing" : "B04_Surface_Watershed_Status_Loading",
),
@@ -514,6 +529,7 @@ export function createWatershedOverlay(onChange: () => void): WatershedOverlay {
);
} finally {
busy = false;
sayBusy(""); // 끝났으면 진행 문구를 거둔다 — 결과는 좌상단 줄에 남는다
button.disabled = false;
button.textContent = L("B04_Surface_Watershed_Btn");
onChange();
@@ -531,6 +547,7 @@ export function createWatershedOverlay(onChange: () => void): WatershedOverlay {
button,
partButtons,
statusElement,
busyElement,
visible: () => shown && analysis !== null,
status: () => statusText,
analysis: () => analysis,