/* ============================================================================= * B06_Section_UI_Cross_View_Zoom.ts * 횡단 카드 그래프의 **확대·축소·팬** 조작구. * * ⚠ 줌·팬 **본문은 공용 조각**(`A00_Common/b_svg_zoom_pan.ts`)으로 옮겼다 * (2026-09-12 사용자 지시 「공용화해줘」) — 계획노선 편집 횡단이 같은 코드를 쓴다. * 여기에는 **B06 것**만 남는다: 카드 여백(`CROSS_PAD`)을 씌운 감싸개, 측점별 배율 기억, * 우측 상단 버튼 묶음. 동작 규칙(휠은 줌이 아님)은 그대로다 — 카드가 수십 장 깔리는 * 화면에서 휠을 줌에 묶으면 목록을 훑을 수가 없다(2026-08-02 사용자 확정). * ========================================================================== */ import { attachSvgZoomPan, type ContentBounds, type ZoomPanHandle, type ZoomPanState, } from "../A00_Common/b_svg_zoom_pan"; import { CROSS_PAD, L } from "./B06_Section_UI_Section_Common"; export type { ContentBounds, ZoomPanHandle, ZoomPanState }; /** * 카드 표시 반폭 조작(2026-08-23 사용자 지시). 카드 하단 ◀/▶/↺을 없애고 우측 상단 * 줌 버튼에 합쳤다 — 원배율에서 −는 폭 넓히기, +는 폭 좁히기, ⤢는 교차점 맞춤이다. */ export interface CrossWidthActions { /** 표시 반폭을 deltaM(m)만큼 조절한다. 계산 반폭을 넘으면 페이지가 재생성까지 처리. */ step: (deltaM: number) => void; /** * 초기화 — 표시 반폭을 전역 보기값으로 되돌린다. 단 그 폭에서 절·성토선과 원지반의 * 교차점이 안 보이는 측점은 교차점이 보이는 폭이 그 측점의 기본값이다. */ fit: () => void; } /** 측점별 줌·팬 상태 — 카드를 다시 만들어도 배율이 살아남는다(2026-08-22 사용자 ③). */ export const cardZoomStates = new Map(); /** 카드 SVG 에 줌·팬을 붙인다 — 여백만 씌워 공용 조각에 넘긴다. 부르는 꼴은 그대로다. */ export function attachZoomPan( svg: SVGSVGElement, plotLayer: SVGGElement, widthPx: number, heightPx: number, /** 이전 카드의 줌·팬 상태 — 조정창 조작으로 카드가 다시 그려져도 배율 유지. */ initial?: ZoomPanState, /** 상태가 바뀔 때마다 부른다 — 카드 밖(뷰)이 담아 뒀다가 다음 렌더에 되돌린다. */ onChange?: (state: ZoomPanState) => void, /** 도형이 실제로 그려진 범위(캐시 보유 폭). 확대 상태에서 팬 한계가 여기까지 늘어난다. */ content?: ContentBounds, ): ZoomPanHandle { return attachSvgZoomPan({ svg, layer: plotLayer, widthPx, heightPx, pad: CROSS_PAD, initial, onChange, content, // 휠은 카드 목록을 훑는 몫이다 — 줌에 안 묶는다. wheelZoom: false, }); } /** * 그래프 우측 상단 줌 버튼(확대/축소/핏). 휠을 대신하는 조작구다. * * `width`를 넘기면 **원배율에서만** 버튼이 표시 반폭을 조절한다(2026-08-23 사용자 지시): * + : 배율 확대(항상) * − : 배율>1이면 축소, 원배율이면 표시 반폭 +1m(계산 반폭 20m를 넘으면 백엔드 재계산) * ⤢ : 배율 원복 + 표시 반폭 초기화(전역 보기값, 교차점이 안 보이면 보이는 폭까지) */ export function buildZoomControls(handle: ZoomPanHandle, width?: CrossWidthActions): HTMLElement { const bar = document.createElement("div"); bar.className = "b06-cross-card__zoom"; const add = (label: string, title: string, action: () => void): void => { const button = document.createElement("button"); button.type = "button"; button.className = "b06-cross-card__zoom-btn"; button.textContent = label; button.title = title; button.addEventListener("click", (event) => { // 카드 선택으로 번지면 그래프가 다시 그려져 방금 맞춘 배율이 날아간다. event.stopPropagation(); action(); }); bar.append(button); }; // +는 언제나 배율 확대다 — 원배율에서 폭 좁히기로 바꿔 놨더니 배율이 1에서 못 올라가 // 가운데 버튼 팬(배율>1에서만 열림)까지 막혔다(2026-08-23 사용자 보고). add("+", L("B06_Profile_View_ZoomIn"), () => handle.zoom(1 / 0.85)); add("−", L("B06_Profile_View_ZoomOut"), () => { if (!width || handle.scale() > 1 + 1e-6) handle.zoom(0.85); else width.step(1); }); add("⤢", L("B06_Profile_View_ZoomFit"), () => { handle.reset(); width?.fit(); }); return bar; }