- 공용 부품 ui_template_gl_map(지도 세우기 · 자료 · 켬끔 · 색 다시 · 카메라) — D03 GL 껍데기를 올림 · D03 은 겹 꼴만(바뀜 없음) - TM 주인 따라가기(B04_PreProcess_UI_MapGl · logic/_MapGl_Frame) — 화면 가운데 1차 맞춤 닮음꼴 카메라 + 남는 늘림(웹 메르카토르 가로세로 0.43 %)은 지도 칸 CSS 행렬 · 칸 둘레 여유 8 px - B04 하단 지도 — 위성 조각(줌인 선명) · 백지도 · 혼합 · 도엽 · 지적 · 행정 · 등고선 겹 GL · 등고 글 · 배수유역 · 계획선 · 관 = 위 캔버스 - B05 배수유역도 — 위성 · 세부유역 채움(짝홀 다각형) · 분수령 · 도엽 GL · 번호 · 상류 세류 · 관 · 강도 = 위 캔버스 - B05 평면 노선 편집 — 바탕칠 · LAS · 도엽 등고선(간격 거름 · 1 m 선) · 하천(LAS 상자 자름) GL · 노선 둘레 띠 = 지도 칸 clip-path · 고른 등고선 · 글 · 노선 · 꼭짓점 = 위 캔버스 - 켬끔 칸(GPU · 세 화면 한 취향 aislo:pref:map.canvas) · WebGL 못 씀 · 잃음 = 옛 캔버스 + 알림 · 누름 · 끌기 판정 손 안 댐 - B04 층 단추 글 = MapLayers gisLayerLabel(지도 본체 700 줄) - 지킴 시험 test_589_2_gl_frame(카메라 대 캔버스 0.5 px · 칸 행렬 늘이기만 · 되돌림 1 mm · 상자 자르기 · 짝홀 다각형) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
5.1 KiB
TypeScript
127 lines
5.1 KiB
TypeScript
/* =============================================================================
|
|
* 2D 지도 레이어 목록·기본값·색 (B04)
|
|
*
|
|
* 어떤 레이어를 다루는지, 처음에 무엇이 켜져 있는지, 무슨 색으로 그리는지만 모은다.
|
|
* 지도 뷰어 본체(`B04_PreProcess_UI_MapViewer.ts`)가 700줄 한계에 닿아 분리했다.
|
|
* 색 값의 정의처는 `ui_template_theme.css`(`--map-*`)이며 여기는 이름만 잇는다.
|
|
* ========================================================================== */
|
|
|
|
import { themeColor } from "@ui/ui_template_palette";
|
|
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
|
|
import { fetchCachedSheetLayer } from "../A00_Common/b_asset_cache";
|
|
import { fetchGisGeoJson } from "./B04_PreProcess_Api_Fetch";
|
|
import type { GeoJsonCollection } from "./B04_PreProcess_UI_MapRender";
|
|
|
|
export const BACKGROUND_LAYERS = ["white", "satellite", "hybrid"] as const;
|
|
// 유수방향은 화면에 쓰지 않기로 해 목록에서 뺐다(2026-08-01 사용자 지시).
|
|
export const GIS_LAYERS = [
|
|
"지적도",
|
|
"행정구역_시군구",
|
|
"행정구역_읍면동",
|
|
"등고선",
|
|
"도엽_등고선",
|
|
"도엽_하천중심선",
|
|
"도엽_표고점",
|
|
"도엽_성절토",
|
|
"도엽_옹벽석축",
|
|
] as const;
|
|
export type BackgroundLayer = (typeof BACKGROUND_LAYERS)[number];
|
|
export type GisLayer = (typeof GIS_LAYERS)[number];
|
|
|
|
/* ── 처음 열었을 때 켜져 있을 레이어 (2026-08-01 사용자 지정) ──────────────
|
|
* 지도가 복잡해지지 않도록 실제로 자주 보는 것만 켠 채로 시작한다.
|
|
* 나머지는 버튼으로 그때그때 켠다. */
|
|
export const BACKGROUND_DEFAULT_ON: Record<BackgroundLayer, boolean> = {
|
|
white: true,
|
|
satellite: true,
|
|
hybrid: false,
|
|
};
|
|
|
|
export const GIS_DEFAULT_ON: Record<GisLayer, boolean> = {
|
|
지적도: false,
|
|
행정구역_시군구: true,
|
|
행정구역_읍면동: true,
|
|
등고선: false,
|
|
도엽_등고선: false,
|
|
도엽_하천중심선: true,
|
|
도엽_표고점: false,
|
|
도엽_성절토: false,
|
|
도엽_옹벽석축: false,
|
|
};
|
|
|
|
/** 받는 중인 층 — 같은 층을 겹쳐 받지 않는다. */
|
|
const inFlight = new Map<string, Promise<GeoJsonCollection | null>>();
|
|
|
|
/** 레이어 하나 받기 — 도엽은 보관함(IndexedDB) · 나머지는 서버 ETag. 실패면 null.
|
|
* 꺼진 층은 켤 때 부른다(처음 열기에 도엽 등고선 37 MB 를 받지 않음). */
|
|
export function fetchGisLayer(
|
|
projectId: string,
|
|
layer: GisLayer,
|
|
): Promise<GeoJsonCollection | null> {
|
|
const key = `${projectId}|${layer}`;
|
|
const pending = inFlight.get(key) ?? downloadLayer(projectId, layer);
|
|
inFlight.set(key, pending);
|
|
void pending.finally(() => inFlight.delete(key));
|
|
return pending;
|
|
}
|
|
|
|
async function downloadLayer(
|
|
projectId: string,
|
|
layer: GisLayer,
|
|
): Promise<GeoJsonCollection | null> {
|
|
try {
|
|
return (
|
|
layer.startsWith("도엽_")
|
|
? await fetchCachedSheetLayer<GeoJsonCollection>(projectId, layer)
|
|
: await fetchGisGeoJson(projectId, layer)
|
|
) as GeoJsonCollection;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** 등고 라벨(계곡선 수치) 기본 표시 여부. */
|
|
export const CONTOUR_LABEL_DEFAULT_ON = false;
|
|
|
|
/** 이만큼(px) 이하로 움직였다 뗐으면 클릭으로 본다 — 손떨림으로 선택이 안 되는 일을 막는다. */
|
|
export const CLICK_SLOP_PX = 4;
|
|
|
|
/** 레이어별 색은 `ui_template_theme.css`의 `--map-*`가 정의처다. 여기는 이름만 잇는다.
|
|
* (fallback 값은 CSS가 아직 안 붙은 첫 프레임 대비용 안전값) */
|
|
const GIS_LAYER_COLOR_TOKENS: Record<GisLayer, [name: string, fallback: string]> = {
|
|
지적도: ["--map-cadastral", "#f97316"],
|
|
행정구역_시군구: ["--map-sigungu", "#7c3aed"],
|
|
행정구역_읍면동: ["--map-eupmyeondong", "#22c55e"],
|
|
등고선: ["--map-contour", "#fdba74"],
|
|
도엽_등고선: ["--map-sheet-contour", "#a5b4fc"],
|
|
도엽_하천중심선: ["--map-sheet-stream", "#2563eb"],
|
|
도엽_표고점: ["--map-sheet-elev-point", "#f9a8d4"],
|
|
도엽_성절토: ["--map-sheet-cutfill", "#f43f5e"],
|
|
도엽_옹벽석축: ["--map-sheet-wall", "#0f766e"],
|
|
};
|
|
|
|
const GIS_LABEL_KEYS: Record<GisLayer, keyof typeof ui_locales> = {
|
|
지적도: "B04_Surface_Map_Cadastral",
|
|
행정구역_시군구: "B04_Surface_Map_Sigungu",
|
|
행정구역_읍면동: "B04_Surface_Map_Eupmyeondong",
|
|
등고선: "B04_Surface_Map_Contour",
|
|
도엽_등고선: "B04_Surface_Map_SheetContour",
|
|
도엽_하천중심선: "B04_Surface_Map_SheetStream",
|
|
도엽_표고점: "B04_Surface_Map_SheetElevPoint",
|
|
도엽_성절토: "B04_Surface_Map_SheetCutFill",
|
|
도엽_옹벽석축: "B04_Surface_Map_SheetWall",
|
|
};
|
|
|
|
/** 층 단추 글(지금 말). */
|
|
export const gisLayerLabel = (layer: GisLayer): string =>
|
|
ui_locales[GIS_LABEL_KEYS[layer]][currentLanguageIndex];
|
|
|
|
export const gisLayerColor = (layer: GisLayer): string =>
|
|
themeColor(...GIS_LAYER_COLOR_TOKENS[layer]);
|
|
|
|
/** 등고 라벨 표기 대상 레이어와 표고 속성 키 (gpkg=CTRLN_HG, 도엽=등고수치) */
|
|
export const CONTOUR_LABEL_KEYS: Partial<Record<GisLayer, string[]>> = {
|
|
등고선: ["CTRLN_HG"],
|
|
도엽_등고선: ["등고수치"],
|
|
};
|