feat(B04·B05): 하단 지도 · 평면 노선 편집 · 배수유역도 바탕 MapLibre 적용 — 공용 GL 부품 · TM 주인 카메라 · 처음 = 켬 · WebGL 못 쓰면 옛 캔버스 (PLAN 589-2 · 요구 448)
- 공용 부품 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>
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/* =============================================================================
|
||||
* B04_PreProcess_UI_MapViewer_Gl.ts
|
||||
* B04 하단 지도 GL 바탕(PLAN 589-2) — 백지도 · 혼합(한 장 그림) · 위성(조각 · 줌인 선명) · 도엽 · 지적 · 행정 ·
|
||||
* 등고선 겹을 MapLibre 로. 등고 글 · 배수유역 · 계획선 · 측점 · 흐름 강도 · 세부유역 · 관 = 위 캔버스 그대로.
|
||||
* 지도 본체(`_MapViewer`)는 켬끔 · 자료 · 따라가기만 부름(700 줄).
|
||||
* ========================================================================== */
|
||||
|
||||
import { getVWorldMapUrl, type VWorldMeta } from "./B04_PreProcess_Api_Fetch";
|
||||
import {
|
||||
BACKGROUND_LAYERS,
|
||||
GIS_LAYERS,
|
||||
gisLayerColor,
|
||||
type BackgroundLayer,
|
||||
type GisLayer,
|
||||
} from "./B04_PreProcess_UI_MapLayers";
|
||||
import { createLayerToggle } from "./B04_PreProcess_UI_LayerToggle";
|
||||
import {
|
||||
createTmGl,
|
||||
GL_TOGGLE_TITLE,
|
||||
lineSpecs,
|
||||
metaCorners,
|
||||
rasterSpec,
|
||||
satelliteData,
|
||||
} from "./B04_PreProcess_UI_MapGl";
|
||||
import {
|
||||
normalizedToScreen,
|
||||
type GeoJsonCollection,
|
||||
type Normalizer,
|
||||
type ViewState,
|
||||
} from "./B04_PreProcess_UI_MapRender";
|
||||
|
||||
type Key = BackgroundLayer | GisLayer;
|
||||
const isContour = (layer: GisLayer): boolean => layer === "등고선" || layer === "도엽_등고선";
|
||||
/** 캔버스와 같은 차례 — 등고선이 맨 밑. */
|
||||
const ORDER = [...GIS_LAYERS].sort((a, b) => (isContour(a) ? -1 : isContour(b) ? 1 : 0));
|
||||
|
||||
export interface SurfaceMapGl {
|
||||
/** 지금 GL 로 그리나 — 참이면 캔버스는 바탕 겹을 쉼 · 그림(img)은 숨김. */
|
||||
on: () => boolean;
|
||||
/** 켠 겹. */
|
||||
sync: (backgrounds: ReadonlySet<BackgroundLayer>, layers: ReadonlySet<GisLayer>) => void;
|
||||
/** 받은 겹(원본 경위도 GeoJSON) — null = 비움. */
|
||||
setLayer: (layer: GisLayer, data: GeoJsonCollection | null) => void;
|
||||
/** 프로젝트 · 메타 — 그림 · 조각 주소(null = 다 비움). */
|
||||
setMeta: (projectId: string | null, meta: VWorldMeta | null) => void;
|
||||
follow: (meta: VWorldMeta | null, normalizer: Normalizer | null, view: ViewState) => void;
|
||||
dispose: () => void;
|
||||
}
|
||||
|
||||
/** `buttons` = 켬끔 칩 자리 · `onChange` = 켬끔이 바뀜(그림 숨김 · 다시 그림). */
|
||||
export function createSurfaceMapGl(
|
||||
viewport: HTMLElement,
|
||||
buttons: HTMLElement,
|
||||
onChange: () => void,
|
||||
): SurfaceMapGl {
|
||||
const toggle = createLayerToggle({
|
||||
label: "GPU",
|
||||
title: GL_TOGGLE_TITLE,
|
||||
onChange: () => tm.toggle(),
|
||||
});
|
||||
toggle.root.dataset.layer = "gl";
|
||||
buttons.append(toggle.root);
|
||||
const tm = createTmGl<Key>({
|
||||
parent: viewport,
|
||||
specs: () => [
|
||||
...BACKGROUND_LAYERS.map((layer) => rasterSpec<Key>(layer)),
|
||||
...ORDER.flatMap((layer) =>
|
||||
lineSpecs<Key>(layer, gisLayerColor(layer), isContour(layer) ? 0.7 : 1.5, {
|
||||
marker: layer === "도엽_표고점" ? "x" : "dot",
|
||||
}),
|
||||
),
|
||||
],
|
||||
themeNames: ["--color-surface", "--map-cadastral", "--map-sheet-contour", "--map-sheet-stream"],
|
||||
onChange: (on) => {
|
||||
toggle.set(on);
|
||||
onChange();
|
||||
},
|
||||
});
|
||||
toggle.set(tm.on());
|
||||
return {
|
||||
on: tm.on,
|
||||
sync(backgrounds, layers) {
|
||||
for (const layer of BACKGROUND_LAYERS) tm.gl.setVisible(layer, backgrounds.has(layer));
|
||||
for (const layer of GIS_LAYERS) tm.gl.setVisible(layer, layers.has(layer));
|
||||
},
|
||||
setLayer: (layer, data) => tm.gl.setData(layer, data),
|
||||
setMeta(projectId, meta) {
|
||||
tm.gl.setData("satellite", projectId ? satelliteData(projectId) : null);
|
||||
for (const layer of ["white", "hybrid"] as const)
|
||||
tm.gl.setData(
|
||||
layer,
|
||||
projectId && meta
|
||||
? {
|
||||
url: location.origin + getVWorldMapUrl(projectId, layer),
|
||||
corners: metaCorners(meta),
|
||||
}
|
||||
: null,
|
||||
);
|
||||
if (!meta) for (const layer of GIS_LAYERS) tm.gl.setData(layer, null);
|
||||
},
|
||||
follow: (meta, normalizer, view) =>
|
||||
tm.follow(
|
||||
meta,
|
||||
normalizer,
|
||||
(nx, ny) => normalizedToScreen(view, nx, ny),
|
||||
view.width,
|
||||
view.height,
|
||||
),
|
||||
dispose: tm.dispose,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user