Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_UI_Cross_Detail_Home.ts
|
|
* [상세] 모달 첫 보기(295-2) — 중심점(중심 십자)이 칸 가운데 · 그림 전체가 들어가게
|
|
* 축마다 중심에서 큰 쪽 반폭으로. [⤢] · 더블클릭 원복도 같은 보기. 카드 보기는 그대로.
|
|
*
|
|
* 가로 반폭 = 카드 반폭(266-1 `homeScale` 이 되좁히던 폭)의 큰 쪽 · 세로 반폭 = 그 가로 안에
|
|
* 그려진 꼭짓점이 중심에서 위 · 아래로 먼 쪽.
|
|
* ========================================================================== */
|
|
|
|
import type { ZoomPanState } from "../A00_Common/b_svg_zoom_pan";
|
|
|
|
type Pt = [number, number];
|
|
interface Rect {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
/** 첫 보기 배율 · 이동 — 중심 `center` 를 `plot` 가운데에. `homeScale` = 1배 대비 카드 반폭 배율. */
|
|
export function detailHomeView(
|
|
points: Pt[],
|
|
center: Pt,
|
|
plot: Rect,
|
|
homeScale: number,
|
|
maxScale: number,
|
|
): ZoomPanState {
|
|
const [cx, cy] = center;
|
|
const halfX = Math.max(cx - plot.x, plot.x + plot.width - cx) / Math.max(homeScale, 1e-6);
|
|
const ys = points.filter(([x]) => Math.abs(x - cx) <= halfX).map(([, y]) => y);
|
|
const halfY = Math.max(1, ...ys.map((y) => Math.abs(y - cy)));
|
|
const scale = Math.min(plot.width / 2 / halfX, plot.height / 2 / halfY, maxScale);
|
|
return {
|
|
scale,
|
|
tx: plot.x + plot.width / 2 - scale * cx,
|
|
ty: plot.y + plot.height / 2 - scale * cy,
|
|
};
|
|
}
|
|
|
|
/** 그림 층의 꺾은선 · 다각형 꼭짓점(그림 px). */
|
|
export function layerPoints(layer: Element): Pt[] {
|
|
return [...layer.querySelectorAll("polyline, polygon")].flatMap((el) =>
|
|
(el.getAttribute("points") ?? "")
|
|
.trim()
|
|
.split(/\s+/)
|
|
.map((pair) => pair.split(",").map(Number))
|
|
.filter((p): p is Pt => p.length === 2 && p.every(Number.isFinite)),
|
|
);
|
|
}
|