- 편집 띠를 CAD 위 절대배치에서 도면 목록 하단 액션 칸으로 옮김 —
1행 편집 띠, 2행 [도각 편집]·[현재 도면 확정] (리본과 겹쳐 문구·버튼이 찌그러지던 문제)
- `drawImage` 가 'broken' 상태 그림에서 던지던 예외로 렌더 루프가 끊겨
이후 모든 도면이 백지로 남던 결함 해소 — 못 읽은 그림은 건너뜀
- `ImageEntity` 가 자리표시자(`{{회사로고}}`)를 절대 URL 로 굳히던 저장 경로 수정 —
원본 주소를 보관해 그대로 돌려주고, 자리표시자는 요청조차 하지 않음
- 버튼 줌(ZOOMIN·ZOOMOUT)이 배율만 바꿔 도면이 화면 밖으로 밀리던 것을
화면 중심 고정으로 수정
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
/** 뷰 탭 — 탐색·재생성 명령 (조사표 7절 중 구현분) */
|
||
import { Point } from '@flatten-js/core';
|
||
import { toast } from 'react-toastify';
|
||
import type { CadCommand } from './command.types';
|
||
import { bumpSceneVersion } from '../helpers/scene-version';
|
||
import { getScreenCanvasDrawController, setEntities, getEntities } from '../state';
|
||
import { Tool } from '../tools';
|
||
import { selectToolStateMachine } from '../tools/select-tool';
|
||
|
||
const zoomBy = (factor: number): string => {
|
||
const controller = getScreenCanvasDrawController();
|
||
const oldScale = controller.getScreenScale();
|
||
const newScale = Math.max(0.01, oldScale * factor);
|
||
// 배율만 바꾸면 화면이 월드 원점 쪽으로 늘어나 도면이 화면 밖으로 밀려난다.
|
||
// 휠 줌이 커서 밑 좌표를 붙잡아 두듯, 버튼 줌은 **화면 중심**의 월드 좌표를
|
||
// 붙잡아 둔다 (screen = (world - offset) * scale).
|
||
const canvasSize = controller.getCanvasSize();
|
||
const offset = controller.getScreenOffset();
|
||
const worldCenterX = offset.x + canvasSize.x / 2 / oldScale;
|
||
const worldCenterY = offset.y + canvasSize.y / 2 / oldScale;
|
||
controller.setScreenScale(newScale);
|
||
controller.setScreenOffset(
|
||
new Point(
|
||
worldCenterX - canvasSize.x / 2 / newScale,
|
||
worldCenterY - canvasSize.y / 2 / newScale
|
||
)
|
||
);
|
||
return `줌 ${Math.round(newScale * 100)}%`;
|
||
};
|
||
|
||
export const VIEW_COMMANDS: CadCommand[] = [
|
||
{
|
||
id: 'SELECT',
|
||
label: '선택',
|
||
aliases: ['SE'],
|
||
glyph: '↖',
|
||
hint: '객체를 클릭하거나 선택 사각형으로 고른다',
|
||
tool: Tool.SELECT,
|
||
machine: selectToolStateMachine,
|
||
},
|
||
{
|
||
id: 'ZOOM',
|
||
label: '범위 줌',
|
||
aliases: ['Z'],
|
||
glyph: '⛶',
|
||
hint: '도면 전체가 보이도록 화면을 맞춘다',
|
||
run: () => {
|
||
getScreenCanvasDrawController().zoomToFitScreen();
|
||
return '도면 전체 보기';
|
||
},
|
||
},
|
||
{
|
||
id: 'ZOOMIN',
|
||
label: '확대',
|
||
glyph: '+',
|
||
run: () => zoomBy(1.25),
|
||
},
|
||
{
|
||
id: 'ZOOMOUT',
|
||
label: '축소',
|
||
glyph: '-',
|
||
run: () => zoomBy(0.8),
|
||
},
|
||
{
|
||
id: 'REGEN',
|
||
label: '재생성',
|
||
aliases: ['RE'],
|
||
glyph: '⟳',
|
||
hint: '화면 캐시를 버리고 객체를 다시 그린다',
|
||
run: () => {
|
||
bumpSceneVersion();
|
||
setEntities([...getEntities()], false);
|
||
return '화면 재생성';
|
||
},
|
||
},
|
||
{
|
||
id: 'PAN',
|
||
label: '초점이동',
|
||
aliases: ['P'],
|
||
glyph: '✋',
|
||
hint: '휠 버튼을 누른 채 끌면 화면이 움직인다',
|
||
run: () => {
|
||
toast.info('휠 버튼을 누른 채 끌면 화면이 이동합니다.');
|
||
return '초점이동 안내';
|
||
},
|
||
},
|
||
];
|