diff --git a/frontend/components/screen/ScreenDesigner.tsx b/frontend/components/screen/ScreenDesigner.tsx index 3d1c19a3..a43f8bcc 100644 --- a/frontend/components/screen/ScreenDesigner.tsx +++ b/frontend/components/screen/ScreenDesigner.tsx @@ -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],