그리드 시스템에 드래그 이동 구현

This commit is contained in:
dohyeons 2025-10-23 09:36:30 +09:00
parent 41c763c019
commit 9bd84f898a
1 changed files with 22 additions and 36 deletions

View File

@ -311,7 +311,7 @@ export function CanvasElement({
const deltaX = e.clientX - dragStartRef.current.x;
const deltaY = e.clientY - dragStartRef.current.y + scrollDelta; // 🔥 스크롤 변화량 반영
// 임시 위치 계산
// 임시 위치 계산 (드래그 중에는 부드럽게 이동)
let rawX = Math.max(0, dragStart.elementX + deltaX);
const rawY = Math.max(0, dragStart.elementY + deltaY);
@ -319,18 +319,12 @@ export function CanvasElement({
const maxX = canvasWidth - element.size.width;
rawX = Math.min(rawX, maxX);
// 자석 스냅으로 변경
const snappedX = magneticSnap(rawX, verticalGuidelines);
const snappedY = magneticSnap(rawY, horizontalGuidelines);
// 스냅 후 X 좌표 다시 체크
const finalSnappedX = Math.min(snappedX, maxX);
setTempPosition({ x: finalSnappedX, y: snappedY });
// 드래그 중에는 스냅 없이 부드럽게 이동
setTempPosition({ x: rawX, y: rawY });
// 🔥 다중 드래그 중 - 다른 위젯들의 위치 업데이트
if (selectedElements.length > 1 && selectedElements.includes(element.id) && onMultiDragMove) {
onMultiDragMove(element, { x: finalSnappedX, y: snappedY });
onMultiDragMove(element, { x: rawX, y: rawY });
}
} else if (isResizing) {
const deltaX = e.clientX - resizeStart.x;
@ -374,21 +368,13 @@ export function CanvasElement({
const maxWidth = canvasWidth - newX;
newWidth = Math.min(newWidth, maxWidth);
// 자석 스냅으로 변경
const snappedX = magneticSnap(newX, verticalGuidelines);
const snappedY = magneticSnap(newY, horizontalGuidelines);
// 리사이즈 중에는 스냅 없이 부드럽게 조절
const boundedX = Math.max(0, Math.min(newX, canvasWidth - newWidth));
const boundedY = Math.max(0, newY);
// 크기는 그리드 박스 단위로 스냅
const snappedWidth = snapSizeToGrid(newWidth, canvasWidth || 1560);
const snappedHeight = snapSizeToGrid(newHeight, canvasWidth || 1560);
// 스냅 후 경계 체크
const finalSnappedX = Math.max(0, Math.min(snappedX, canvasWidth - snappedWidth));
const finalSnappedY = Math.max(0, snappedY);
// 임시 크기/위치 저장 (스냅됨)
setTempPosition({ x: finalSnappedX, y: finalSnappedY });
setTempSize({ width: snappedWidth, height: snappedHeight });
// 임시 크기/위치 저장 (부드러운 이동)
setTempPosition({ x: boundedX, y: boundedY });
setTempSize({ width: newWidth, height: newHeight });
}
},
[
@ -412,10 +398,9 @@ export function CanvasElement({
// 마우스 업 처리 (이미 스냅된 위치 사용)
const handleMouseUp = useCallback(() => {
if (isDragging && tempPosition) {
// tempPosition은 이미 드래그 중에 마그네틱 스냅 적용됨
// 다시 스냅하지 않고 그대로 사용!
let finalX = tempPosition.x;
const finalY = tempPosition.y;
// 마우스를 놓을 때 그리드에 스냅
let finalX = magneticSnap(tempPosition.x, verticalGuidelines);
const finalY = magneticSnap(tempPosition.y, horizontalGuidelines);
// X 좌표가 캔버스 너비를 벗어나지 않도록 최종 제한
const maxX = canvasWidth - element.size.width;
@ -473,20 +458,19 @@ export function CanvasElement({
}
if (isResizing && tempPosition && tempSize) {
// tempPosition과 tempSize는 이미 리사이즈 중에 마그네틱 스냅 적용됨
// 다시 스냅하지 않고 그대로 사용!
const finalX = tempPosition.x;
const finalY = tempPosition.y;
let finalWidth = tempSize.width;
const finalHeight = tempSize.height;
// 마우스를 놓을 때 그리드에 스냅
const finalX = magneticSnap(tempPosition.x, verticalGuidelines);
const finalY = magneticSnap(tempPosition.y, horizontalGuidelines);
const finalWidth = snapSizeToGrid(tempSize.width, canvasWidth || 1560);
const finalHeight = snapSizeToGrid(tempSize.height, canvasWidth || 1560);
// 가로 너비가 캔버스를 벗어나지 않도록 최종 제한
const maxWidth = canvasWidth - finalX;
finalWidth = Math.min(finalWidth, maxWidth);
const boundedWidth = Math.min(finalWidth, maxWidth);
onUpdate(element.id, {
position: { x: finalX, y: finalY },
size: { width: finalWidth, height: finalHeight },
size: { width: boundedWidth, height: finalHeight },
});
setTempPosition(null);
@ -518,6 +502,8 @@ export function CanvasElement({
allElements,
dragStart.elementX,
dragStart.elementY,
verticalGuidelines,
horizontalGuidelines,
]);
// 🔥 자동 스크롤 루프 (requestAnimationFrame 사용)