feat(D 예정노선): 줌아웃 한도 인자 · 느린 조작 시간 표식 (PLAN 600-3 · 600-4 · 요구 463-27)

- 휠 부품 하한 인자 minScale(안 주면 0.5 = B05 그대로) · 예정노선 지도만 화면 폭 약 600 km(한반도)까지 뺌
- performance 표식 perfTime — 지도 다시 그림 · GL 카메라 · 바탕 · 위 그림 · 마우스 움직임(__aisloPerf 켰을 때만)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 15:15:08 +09:00
co-authored by Claude Sonnet 5.5
parent 7ae441be67
commit da473b041b
3 changed files with 41 additions and 10 deletions
+22 -7
View File
@@ -16,6 +16,7 @@
* 모두 `view` 를 바꾸고 `draw()` → 한 화면 한 번 `glCamera` 로 MapLibre 를 맞춘 뒤 캔버스를 그림.
* ========================================================================== */
import { perfTime } from "@ui/ui_template_gl_map";
import { createMapTools, mapToolButton } from "@ui/ui_template_map_tools";
import { routeColor, themeColor } from "@ui/ui_template_palette";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
@@ -60,6 +61,9 @@ export function planColors(): {
};
}
/** 줌아웃 한도(600-3) — 화면 폭 약 600 km(한반도 · 위성 z6). 휠 하한 배율 = 이 폭이 화면에 드는 값(B05 는 0.5 그대로). */
export const MAP_MAX_VIEW_WIDTH_M = 600_000;
/** 위성이 없을 때 맞출 점 둘레로 둘 가짜 도엽 여유(m). */
const FAKE_MARGIN_M = 600;
@@ -406,9 +410,11 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
function flush(): void {
cancelAnimationFrame(frame);
frame = 0;
if (baseDirty) glCamera();
if (baseDirty) paint(baseContext, true);
if (topDirty) paint(context, false);
perfTime("plan:flush", () => {
if (baseDirty) perfTime("plan:glCamera", glCamera);
if (baseDirty) perfTime("plan:paintBase", () => paint(baseContext, true));
if (topDirty) perfTime("plan:paintTop", () => paint(context, false));
});
baseDirty = topDirty = false;
}
/** 다음 화면에 한 번 — 바탕까지(화면 · 겹이 바뀜) 또는 위만(마우스). */
@@ -455,10 +461,12 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
});
canvas.addEventListener("pointermove", (event) => {
if (!meta || event.buttons & 4) return; // 가운데 단추 옮기는 중
const [px, py] = at(event);
const map = screenMap();
for (const layer of layers) layer.hover?.(px, py, map);
drawTop();
perfTime("plan:pointermove", () => {
const [px, py] = at(event);
const map = screenMap();
for (const layer of layers) layer.hover?.(px, py, map);
drawTop();
});
});
canvas.addEventListener("pointerleave", () => {
for (const layer of layers) layer.leave?.();
@@ -502,6 +510,13 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
getMeta: () => meta,
unrotateDelta: rotation.unrotateDelta,
rotateWheel: rotation.wheel,
minScale: () =>
meta && view.mapRect.width > 0
? Math.min(
0.5,
(view.width * meta.width_meters) / (view.mapRect.width * MAP_MAX_VIEW_WIDTH_M),
)
: 0.5,
draw,
});