Files
Aislo/B07_DesignDetail/openwebcad/src/drawControllers/fit-view.ts
T
eomsangdonandClaude Opus 5.5 9f0ab53c53 fix(B07-CAD): 커서 입력창 칸 · 글 색이 테마를 따름 — 자동색 뒤집기 건너뜀(97-1)
- 칸 = --cad-chrome-raised(밝음 흰 칸 + --cad-line 테두리 · 어두움 #251f38) · 글 = --cad-text · 안내 = --cad-text-dim
- fillRectScreen · drawTextScreen 에 paintColor 건너뛰는 rawColor 선택 인자
- 입력창 그리기를 inputController/input-field-draw.ts 로 · 전체 맞춤 계산을 drawControllers/fit-view.ts 로(700줄)
- App.consts 입력창 색 상수 = 토큰 폴백 · 틀린 주석 고침
- 시험 theme-auto-color: 칸 · 글 색이 두 테마 모두 다름

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
2026-10-08 13:50:07 +09:00

48 lines
2.5 KiB
TypeScript

/** 전체 맞춤 계산 — 맞출 개체 고르기 · 배율 · 화면 원점(`screenCanvas.drawController.ts` zoomToFitScreen 이 부름). */
import { Point } from '@flatten-js/core';
import type { Entity } from '../entities/Entity.ts';
import { getBoundingBoxOfMultipleEntities } from '../helpers/get-bounding-box-of-multiple-entities.ts';
import { getEntities, getPickableEntities } from '../state.ts';
/** M02 가 구조물 도면에 얹는 도각 층 — 서버 `STRUCTURE_FRAME_LAYER` 와 같음 */
const STRUCTURE_FRAME_LAYER_ID = 'm02-structure-frame';
/** 맞출 개체 */
export function fitEntities(): Entity[] {
// 도각·원지반 같은 잠금 도면층은 빼고 설계 콘텐츠에만 맞춘다 (2026-08-31 사용자
// 확정). 도각까지 넣으면 A1 한 장 전체가 잡혀 화면의 40%가 여백으로 간다.
// 구조물 도면(M02·B08)은 얹은 도각(작도 틀)이 있으면 도각 전체에 맞춘다 — 옛 DXF 가 자기 도곽·
// 표제 띠를 품어 범위가 크면 도각이 화면 밖으로 밀린다.
const structureFrame = getEntities().filter((e) => e.layerId === STRUCTURE_FRAME_LAYER_ID);
const pickable = getPickableEntities();
return structureFrame.length ? structureFrame : pickable.length ? pickable : getEntities();
}
/** 개체 범위를 화면 가운데에 놓는 배율 · 화면 원점(월드 좌표) */
export function fitView(entities: Entity[], canvasSize: Point): { zoom: number; offset: Point } {
const boundingBox = getBoundingBoxOfMultipleEntities(entities);
const boundingWidth = boundingBox.maxX - boundingBox.minX;
const boundingHeight = boundingBox.maxY - boundingBox.minY;
// 10% 여백을 남기고 두 축 중 더 빡빡한 쪽에 맞춘다 (종횡비 유지)
const FIT_MARGIN = 0.9;
const scaleX =
boundingWidth > 0 ? (canvasSize.x * FIT_MARGIN) / boundingWidth : Number.POSITIVE_INFINITY;
const scaleY =
boundingHeight > 0 ? (canvasSize.y * FIT_MARGIN) / boundingHeight : Number.POSITIVE_INFINITY;
let zoomLevel = Math.min(scaleX, scaleY);
if (!Number.isFinite(zoomLevel) || zoomLevel <= 0) zoomLevel = 1;
// screen = (world - offset) * zoom 이므로, 도면 중심을 화면 중심에 맞추려면
// offset = worldCenter - (화면 절반 픽셀) / zoom
const worldCenterX = (boundingBox.minX + boundingBox.maxX) / 2;
const worldCenterY = (boundingBox.minY + boundingBox.maxY) / 2;
return {
zoom: zoomLevel,
offset: new Point(
worldCenterX - canvasSize.x / 2 / zoomLevel,
worldCenterY - canvasSize.y / 2 / zoomLevel
),
};
}