타입별 상세설정 추가
This commit is contained in:
@@ -113,6 +113,38 @@ export function calculateWidthFromColumns(columns: number, gridInfo: GridInfo, g
|
||||
return columns * columnWidth + (columns - 1) * gap;
|
||||
}
|
||||
|
||||
/**
|
||||
* gridColumns 속성을 기반으로 컴포넌트 크기 업데이트
|
||||
*/
|
||||
export function updateSizeFromGridColumns(
|
||||
component: { gridColumns?: number; size: Size },
|
||||
gridInfo: GridInfo,
|
||||
gridSettings: GridSettings,
|
||||
): Size {
|
||||
if (!component.gridColumns || component.gridColumns < 1) {
|
||||
return component.size;
|
||||
}
|
||||
|
||||
const newWidth = calculateWidthFromColumns(component.gridColumns, gridInfo, gridSettings);
|
||||
|
||||
return {
|
||||
width: newWidth,
|
||||
height: component.size.height, // 높이는 유지
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트의 gridColumns를 자동으로 크기에 맞게 조정
|
||||
*/
|
||||
export function adjustGridColumnsFromSize(
|
||||
component: { size: Size },
|
||||
gridInfo: GridInfo,
|
||||
gridSettings: GridSettings,
|
||||
): number {
|
||||
const columns = calculateColumnsFromWidth(component.size.width, gridInfo, gridSettings);
|
||||
return Math.min(Math.max(1, columns), gridSettings.columns); // 1-12 범위로 제한
|
||||
}
|
||||
|
||||
/**
|
||||
* 너비에서 격자 컬럼 수 계산
|
||||
*/
|
||||
@@ -180,3 +212,170 @@ export function isOnGridBoundary(
|
||||
|
||||
return positionMatch && sizeMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* 그룹 내부 컴포넌트들을 격자에 맞게 정렬
|
||||
*/
|
||||
export function alignGroupChildrenToGrid(
|
||||
children: any[],
|
||||
groupPosition: Position,
|
||||
gridInfo: GridInfo,
|
||||
gridSettings: GridSettings,
|
||||
): any[] {
|
||||
if (!gridSettings.snapToGrid || children.length === 0) return children;
|
||||
|
||||
console.log("🔧 alignGroupChildrenToGrid 시작:", {
|
||||
childrenCount: children.length,
|
||||
groupPosition,
|
||||
gridInfo,
|
||||
gridSettings,
|
||||
});
|
||||
|
||||
return children.map((child, index) => {
|
||||
console.log(`📐 자식 ${index + 1} 처리 중:`, {
|
||||
childId: child.id,
|
||||
originalPosition: child.position,
|
||||
originalSize: child.size,
|
||||
});
|
||||
|
||||
const { columnWidth } = gridInfo;
|
||||
const { gap } = gridSettings;
|
||||
|
||||
// 그룹 내부 패딩 고려한 격자 정렬
|
||||
const padding = 16;
|
||||
const effectiveX = child.position.x - padding;
|
||||
const columnIndex = Math.round(effectiveX / (columnWidth + gap));
|
||||
const snappedX = padding + columnIndex * (columnWidth + gap);
|
||||
|
||||
// Y 좌표는 20px 단위로 스냅
|
||||
const effectiveY = child.position.y - padding;
|
||||
const rowIndex = Math.round(effectiveY / 20);
|
||||
const snappedY = padding + rowIndex * 20;
|
||||
|
||||
// 크기는 외부 격자와 동일하게 스냅 (columnWidth + gap 사용)
|
||||
const fullColumnWidth = columnWidth + gap; // 외부 격자와 동일한 크기
|
||||
const widthInColumns = Math.max(1, Math.round(child.size.width / fullColumnWidth));
|
||||
const snappedWidth = widthInColumns * fullColumnWidth - gap; // gap 제거하여 실제 컴포넌트 크기
|
||||
const snappedHeight = Math.max(40, Math.round(child.size.height / 20) * 20);
|
||||
|
||||
const snappedChild = {
|
||||
...child,
|
||||
position: {
|
||||
x: Math.max(padding, snappedX), // 패딩만큼 최소 여백 확보
|
||||
y: Math.max(padding, snappedY),
|
||||
z: child.position.z || 1,
|
||||
},
|
||||
size: {
|
||||
width: snappedWidth,
|
||||
height: snappedHeight,
|
||||
},
|
||||
};
|
||||
|
||||
console.log(`✅ 자식 ${index + 1} 격자 정렬 완료:`, {
|
||||
childId: child.id,
|
||||
calculation: {
|
||||
effectiveX,
|
||||
effectiveY,
|
||||
columnIndex,
|
||||
rowIndex,
|
||||
widthInColumns,
|
||||
originalX: child.position.x,
|
||||
snappedX: snappedChild.position.x,
|
||||
padding,
|
||||
},
|
||||
snappedPosition: snappedChild.position,
|
||||
snappedSize: snappedChild.size,
|
||||
deltaX: snappedChild.position.x - child.position.x,
|
||||
deltaY: snappedChild.position.y - child.position.y,
|
||||
});
|
||||
|
||||
return snappedChild;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 그룹 생성 시 최적화된 그룹 크기 계산
|
||||
*/
|
||||
export function calculateOptimalGroupSize(
|
||||
children: Array<{ position: Position; size: Size }>,
|
||||
gridInfo: GridInfo,
|
||||
gridSettings: GridSettings,
|
||||
): Size {
|
||||
if (children.length === 0) {
|
||||
return { width: gridInfo.columnWidth * 2, height: 40 * 2 };
|
||||
}
|
||||
|
||||
console.log("📏 calculateOptimalGroupSize 시작:", {
|
||||
childrenCount: children.length,
|
||||
children: children.map((c) => ({ pos: c.position, size: c.size })),
|
||||
});
|
||||
|
||||
// 모든 자식 컴포넌트를 포함하는 최소 경계 계산
|
||||
const bounds = children.reduce(
|
||||
(acc, child) => ({
|
||||
minX: Math.min(acc.minX, child.position.x),
|
||||
minY: Math.min(acc.minY, child.position.y),
|
||||
maxX: Math.max(acc.maxX, child.position.x + child.size.width),
|
||||
maxY: Math.max(acc.maxY, child.position.y + child.size.height),
|
||||
}),
|
||||
{ minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },
|
||||
);
|
||||
|
||||
console.log("📐 경계 계산:", bounds);
|
||||
|
||||
const contentWidth = bounds.maxX - bounds.minX;
|
||||
const contentHeight = bounds.maxY - bounds.minY;
|
||||
|
||||
// 그룹은 격자 스냅 없이 컨텐츠에 맞는 자연스러운 크기
|
||||
const padding = 16; // 그룹 내부 여백
|
||||
const groupSize = {
|
||||
width: contentWidth + padding * 2,
|
||||
height: contentHeight + padding * 2,
|
||||
};
|
||||
|
||||
console.log("✅ 자연스러운 그룹 크기:", {
|
||||
contentSize: { width: contentWidth, height: contentHeight },
|
||||
withPadding: groupSize,
|
||||
strategy: "그룹은 격자 스냅 없이, 내부 컴포넌트만 격자에 맞춤",
|
||||
});
|
||||
|
||||
return groupSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 그룹 내 상대 좌표를 격자 기준으로 정규화
|
||||
*/
|
||||
export function normalizeGroupChildPositions(children: any[], gridSettings: GridSettings): any[] {
|
||||
if (!gridSettings.snapToGrid || children.length === 0) return children;
|
||||
|
||||
console.log("🔄 normalizeGroupChildPositions 시작:", {
|
||||
childrenCount: children.length,
|
||||
originalPositions: children.map((c) => ({ id: c.id, pos: c.position })),
|
||||
});
|
||||
|
||||
// 모든 자식의 최소 위치 찾기
|
||||
const minX = Math.min(...children.map((child) => child.position.x));
|
||||
const minY = Math.min(...children.map((child) => child.position.y));
|
||||
|
||||
console.log("📍 최소 위치:", { minX, minY });
|
||||
|
||||
// 그룹 내에서 시작점을 패딩만큼 떨어뜨림 (자연스러운 여백)
|
||||
const padding = 16;
|
||||
const startX = padding;
|
||||
const startY = padding;
|
||||
|
||||
const normalizedChildren = children.map((child) => ({
|
||||
...child,
|
||||
position: {
|
||||
x: child.position.x - minX + startX,
|
||||
y: child.position.y - minY + startY,
|
||||
z: child.position.z || 1,
|
||||
},
|
||||
}));
|
||||
|
||||
console.log("✅ 정규화 완료:", {
|
||||
normalizedPositions: normalizedChildren.map((c) => ({ id: c.id, pos: c.position })),
|
||||
});
|
||||
|
||||
return normalizedChildren;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user