Merge remote-tracking branch 'origin/sub_laptop_2' into main_laptop_1

This commit is contained in:
2026-11-01 11:44:11 +09:00
11 changed files with 591 additions and 339 deletions
+18 -63
View File
@@ -38,7 +38,7 @@ import type { GlBase } from "./D03_PlanAnalysis_UI_MapGl";
import type { Vertex } from "./logic/D03_PlanAnalysis_Plan";
import { localTmFrame, tmParams } from "./logic/D03_PlanAnalysis_Tm";
/** 「연도 구역 마커」 끌어 놓기 자료 꼴(585-3 · 단추 = 그리기 칸 599-4). */
/** 「연도 구역 마커」 끌어 놓기 자료 꼴(585-3 · 단추 = 그리기 칸 599-4 · 받음 = 키트 `bindPlanInput`). */
export const YEAR_MARK_DRAG = "application/x-aislo-year-mark";
/** 측점 간격(m) — B 규칙 측점과 같음. */
@@ -157,6 +157,14 @@ export interface PlanMap {
screenOfLonLat: (lon: number, lat: number) => [number, number] | null;
/** 검증 창구 — 지금 돌린 각(도). */
rotationDeg: () => number;
/** 지도 입력 — 누름 · 맴돎 · 놓음 · 우클릭을 겹에 나눠 줄 재료(`bindPlanInput`). */
input: {
canvas: HTMLCanvasElement;
at: (event: MouseEvent) => [number, number];
screen: () => ScreenMap | null;
layers: () => PlanMapLayer[];
redraw: () => void;
};
dispose: () => void;
}
@@ -444,71 +452,11 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
flush();
}
/** 누른 화면 자리 → 그림 px(돌리기 전). */
const at = (event: PointerEvent | MouseEvent): [number, number] => {
/** 누른 화면 자리 → 그림 px(돌리기 전) · 나눠 주기 = `bindPlanInput`(키트 · 페이지가 묶음). */
const at = (event: MouseEvent): [number, number] => {
const rect = canvas.getBoundingClientRect();
return rotation.unrotate(event.clientX - rect.left, event.clientY - rect.top);
};
canvas.addEventListener("pointerdown", (event) => {
if (!meta || event.button !== 0) return;
const [px, py] = at(event);
const map = screenMap();
if (layers.some((layer) => layer.press?.(px, py, map, 0, event.shiftKey))) {
canvas.setPointerCapture(event.pointerId); // 끌기가 캔버스 밖으로 나가도 놓음을 받음
drawTop();
}
});
canvas.addEventListener("pointerup", (event) => {
if (event.button !== 0 || !meta) return;
const map = screenMap();
for (const layer of layers) layer.release?.(map);
drawTop();
});
canvas.addEventListener("pointermove", (event) => {
if (!meta || event.buttons & 4) return; // 가운데 단추 옮기는 중
perfTime("plan:pointermove", () => {
const [px, py] = at(event);
const map = screenMap();
for (const layer of layers) layer.hover?.(px, py, map, event.shiftKey);
drawTop();
});
});
canvas.addEventListener("pointerleave", () => {
for (const layer of layers) layer.leave?.();
drawTop();
});
const markDrag = (event: DragEvent): boolean =>
!!meta && !!event.dataTransfer?.types.includes(YEAR_MARK_DRAG);
canvas.addEventListener("dragover", (event) => {
if (!markDrag(event)) return;
const [px, py] = at(event);
const map = screenMap();
if (layers.some((layer) => layer.dragOver?.(px, py, map))) {
event.preventDefault();
event.dataTransfer!.dropEffect = "copy";
}
drawTop();
});
canvas.addEventListener("drop", (event) => {
if (!markDrag(event)) return;
event.preventDefault();
const [px, py] = at(event);
const map = screenMap();
layers.some((layer) => layer.drop?.(px, py, map));
drawTop();
});
canvas.addEventListener("dragleave", () => {
for (const layer of layers) layer.leave?.();
drawTop();
});
canvas.addEventListener("contextmenu", (event) => {
event.preventDefault();
if (!meta) return;
const [px, py] = at(event);
const map = screenMap();
if (layers.some((layer) => layer.press?.(px, py, map, 2, event.shiftKey))) drawTop();
});
bindRouteEditNavigation({
canvas,
getView: () => view,
@@ -572,6 +520,13 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
screenOfLonLat: (lon, lat) =>
scene.meta ? rotation.rerotate(...lonLat(scene.meta).project(lon, lat)) : null,
rotationDeg: () => (rotation.radians() * 180) / Math.PI,
input: {
canvas,
at,
screen: () => (meta ? screenMap() : null),
layers: () => layers,
redraw: drawTop,
},
dispose: () => {
gl?.enable(null);
observer.disconnect();