리사이즈

This commit is contained in:
leeheejin 2025-10-23 11:25:28 +09:00
parent 5e1d2507da
commit 8ab36f32a0
1 changed files with 105 additions and 8 deletions

View File

@ -1189,32 +1189,129 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
[layout, screenResolution, saveToHistory],
);
// 해상도 변경 핸들러
// 해상도 변경 핸들러 (자동 스케일링 포함)
const handleResolutionChange = useCallback(
(newResolution: ScreenResolution) => {
const oldWidth = screenResolution.width;
const oldHeight = screenResolution.height;
const newWidth = newResolution.width;
const newHeight = newResolution.height;
console.log("📱 해상도 변경 시작:", {
from: `${screenResolution.width}x${screenResolution.height}`,
to: `${newResolution.width}x${newResolution.height}`,
from: `${oldWidth}x${oldHeight}`,
to: `${newWidth}x${newHeight}`,
hasComponents: layout.components.length > 0,
snapToGrid: layout.gridSettings?.snapToGrid || false,
});
setScreenResolution(newResolution);
// 해상도 변경 시에는 격자 스냅을 적용하지 않고 해상도 정보만 업데이트
// 이는 기존 컴포넌트들의 위치를 보존하기 위함
// 컴포넌트가 없으면 해상도만 변경
if (layout.components.length === 0) {
const updatedLayout = {
...layout,
screenResolution: newResolution,
};
setLayout(updatedLayout);
saveToHistory(updatedLayout);
console.log("✅ 해상도 변경 완료 (컴포넌트 없음)");
return;
}
// 비율 계산
const scaleX = newWidth / oldWidth;
const scaleY = newHeight / oldHeight;
console.log("📐 스케일링 비율:", {
scaleX: `${(scaleX * 100).toFixed(2)}%`,
scaleY: `${(scaleY * 100).toFixed(2)}%`,
});
// 컴포넌트 재귀적으로 스케일링하는 함수
const scaleComponent = (comp: ComponentData): ComponentData => {
// 위치 스케일링
const scaledPosition = {
x: comp.position.x * scaleX,
y: comp.position.y * scaleY,
z: comp.position.z || 1,
};
// 크기 스케일링
const scaledSize = {
width: comp.size.width * scaleX,
height: comp.size.height * scaleY,
};
return {
...comp,
position: scaledPosition,
size: scaledSize,
};
};
// 모든 컴포넌트 스케일링 (그룹의 자식도 자동으로 스케일링됨)
const scaledComponents = layout.components.map(scaleComponent);
console.log("🔄 컴포넌트 스케일링 완료:", {
totalComponents: scaledComponents.length,
groupComponents: scaledComponents.filter((c) => c.type === "group").length,
note: "그룹의 자식 컴포넌트도 모두 스케일링됨",
});
// 격자 스냅이 활성화된 경우 격자에 맞춰 재조정
let finalComponents = scaledComponents;
if (layout.gridSettings?.snapToGrid) {
const newGridInfo = calculateGridInfo(newWidth, newHeight, {
columns: layout.gridSettings.columns,
gap: layout.gridSettings.gap,
padding: layout.gridSettings.padding,
snapToGrid: layout.gridSettings.snapToGrid || false,
});
const gridUtilSettings = {
columns: layout.gridSettings.columns,
gap: layout.gridSettings.gap,
padding: layout.gridSettings.padding,
snapToGrid: layout.gridSettings.snapToGrid,
};
finalComponents = scaledComponents.map((comp) => {
const snappedPosition = snapToGrid(comp.position, newGridInfo, gridUtilSettings);
const snappedSize = snapSizeToGrid(comp.size, newGridInfo, gridUtilSettings);
// gridColumns 재계산
const adjustedGridColumns = adjustGridColumnsFromSize({ size: snappedSize }, newGridInfo, gridUtilSettings);
return {
...comp,
position: snappedPosition,
size: snappedSize,
gridColumns: adjustedGridColumns,
};
});
console.log("🧲 격자 스냅 적용 완료");
}
const updatedLayout = {
...layout,
components: finalComponents,
screenResolution: newResolution,
};
setLayout(updatedLayout);
saveToHistory(updatedLayout);
toast.success(`해상도 변경 완료! ${scaledComponents.length}개 컴포넌트가 자동으로 조정되었습니다.`, {
description: `${oldWidth}×${oldHeight}${newWidth}×${newHeight}`,
});
console.log("✅ 해상도 변경 완료:", {
newResolution: `${newResolution.width}x${newResolution.height}`,
preservedComponents: layout.components.length,
note: "컴포넌트 위치는 보존됨 (격자 스냅 생략)",
newResolution: `${newWidth}x${newHeight}`,
scaledComponents: finalComponents.length,
scaleX: `${(scaleX * 100).toFixed(2)}%`,
scaleY: `${(scaleY * 100).toFixed(2)}%`,
note: "모든 컴포넌트가 비율에 맞게 자동 조정됨",
});
},
[layout, saveToHistory, screenResolution],