정렬 가이드라인 구현

This commit is contained in:
dohyeons
2025-10-01 15:35:16 +09:00
parent ae23a4408e
commit c5c6d9239c
3 changed files with 120 additions and 4 deletions

View File

@@ -9,8 +9,15 @@ interface CanvasComponentProps {
}
export function CanvasComponent({ component }: CanvasComponentProps) {
const { selectedComponentId, selectComponent, updateComponent, getQueryResult, snapValueToGrid } =
useReportDesigner();
const {
selectedComponentId,
selectComponent,
updateComponent,
getQueryResult,
snapValueToGrid,
calculateAlignmentGuides,
clearAlignmentGuides,
} = useReportDesigner();
const [isDragging, setIsDragging] = useState(false);
const [isResizing, setIsResizing] = useState(false);
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
@@ -54,10 +61,16 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
if (isDragging) {
const newX = Math.max(0, e.clientX - dragStart.x);
const newY = Math.max(0, e.clientY - dragStart.y);
const snappedX = snapValueToGrid(newX);
const snappedY = snapValueToGrid(newY);
// 정렬 가이드라인 계산
calculateAlignmentGuides(component.id, snappedX, snappedY, component.width, component.height);
// Grid Snap 적용
updateComponent(component.id, {
x: snapValueToGrid(newX),
y: snapValueToGrid(newY),
x: snappedX,
y: snappedY,
});
} else if (isResizing) {
const deltaX = e.clientX - resizeStart.x;
@@ -75,6 +88,8 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
const handleMouseUp = () => {
setIsDragging(false);
setIsResizing(false);
// 가이드라인 초기화
clearAlignmentGuides();
};
document.addEventListener("mousemove", handleMouseMove);
@@ -94,8 +109,12 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
resizeStart.width,
resizeStart.height,
component.id,
component.width,
component.height,
updateComponent,
snapValueToGrid,
calculateAlignmentGuides,
clearAlignmentGuides,
]);
// 표시할 값 결정

View File

@@ -20,6 +20,7 @@ export function ReportDesignerCanvas() {
showGrid,
gridSize,
snapValueToGrid,
alignmentGuides,
} = useReportDesigner();
const [{ isOver }, drop] = useDrop(() => ({
@@ -109,6 +110,32 @@ export function ReportDesignerCanvas() {
}}
onClick={handleCanvasClick}
>
{/* 정렬 가이드라인 렌더링 */}
{alignmentGuides.vertical.map((x, index) => (
<div
key={`v-${index}`}
className="pointer-events-none absolute top-0 bottom-0"
style={{
left: `${x}px`,
width: "1px",
backgroundColor: "#ef4444",
zIndex: 9999,
}}
/>
))}
{alignmentGuides.horizontal.map((y, index) => (
<div
key={`h-${index}`}
className="pointer-events-none absolute right-0 left-0"
style={{
top: `${y}px`,
height: "1px",
backgroundColor: "#ef4444",
zIndex: 9999,
}}
/>
))}
{/* 컴포넌트 렌더링 */}
{components.map((component) => (
<CanvasComponent key={component.id} component={component} />