캔버스 여백 설정
This commit is contained in:
parent
27e33e27d1
commit
4e1e5b0d51
|
|
@ -22,6 +22,7 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
|
|||
clearAlignmentGuides,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
margins,
|
||||
} = useReportDesigner();
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
|
|
@ -99,16 +100,24 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
|
|||
const newX = Math.max(0, e.clientX - dragStart.x);
|
||||
const newY = Math.max(0, e.clientY - dragStart.y);
|
||||
|
||||
// 캔버스 경계 체크 (mm를 px로 변환: 1mm ≈ 3.7795px)
|
||||
// 여백을 px로 변환 (1mm ≈ 3.7795px)
|
||||
const marginTopPx = margins.top * 3.7795;
|
||||
const marginBottomPx = margins.bottom * 3.7795;
|
||||
const marginLeftPx = margins.left * 3.7795;
|
||||
const marginRightPx = margins.right * 3.7795;
|
||||
|
||||
// 캔버스 경계 체크 (mm를 px로 변환)
|
||||
const canvasWidthPx = canvasWidth * 3.7795;
|
||||
const canvasHeightPx = canvasHeight * 3.7795;
|
||||
|
||||
// 컴포넌트가 캔버스 안에 있도록 제한
|
||||
const maxX = canvasWidthPx - component.width;
|
||||
const maxY = canvasHeightPx - component.height;
|
||||
// 컴포넌트가 여백 안에 있도록 제한
|
||||
const minX = marginLeftPx;
|
||||
const minY = marginTopPx;
|
||||
const maxX = canvasWidthPx - marginRightPx - component.width;
|
||||
const maxY = canvasHeightPx - marginBottomPx - component.height;
|
||||
|
||||
const boundedX = Math.min(Math.max(0, newX), maxX);
|
||||
const boundedY = Math.min(Math.max(0, newY), maxY);
|
||||
const boundedX = Math.min(Math.max(minX, newX), maxX);
|
||||
const boundedY = Math.min(Math.max(minY, newY), maxY);
|
||||
|
||||
const snappedX = snapValueToGrid(boundedX);
|
||||
const snappedY = snapValueToGrid(boundedY);
|
||||
|
|
@ -150,13 +159,17 @@ export function CanvasComponent({ component }: CanvasComponentProps) {
|
|||
const newWidth = Math.max(50, resizeStart.width + deltaX);
|
||||
const newHeight = Math.max(30, resizeStart.height + deltaY);
|
||||
|
||||
// 여백을 px로 변환
|
||||
const marginRightPx = margins.right * 3.7795;
|
||||
const marginBottomPx = margins.bottom * 3.7795;
|
||||
|
||||
// 캔버스 경계 체크
|
||||
const canvasWidthPx = canvasWidth * 3.7795;
|
||||
const canvasHeightPx = canvasHeight * 3.7795;
|
||||
|
||||
// 컴포넌트가 캔버스를 벗어나지 않도록 최대 크기 제한
|
||||
const maxWidth = canvasWidthPx - component.x;
|
||||
const maxHeight = canvasHeightPx - component.y;
|
||||
// 컴포넌트가 여백을 벗어나지 않도록 최대 크기 제한
|
||||
const maxWidth = canvasWidthPx - marginRightPx - component.x;
|
||||
const maxHeight = canvasHeightPx - marginBottomPx - component.y;
|
||||
|
||||
const boundedWidth = Math.min(newWidth, maxWidth);
|
||||
const boundedHeight = Math.min(newHeight, maxHeight);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export function ReportDesignerCanvas() {
|
|||
updateComponent,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
margins,
|
||||
selectComponent,
|
||||
selectedComponentId,
|
||||
selectedComponentIds,
|
||||
|
|
@ -66,12 +67,33 @@ export function ReportDesignerCanvas() {
|
|||
height = 70;
|
||||
}
|
||||
|
||||
// 여백을 px로 변환 (1mm ≈ 3.7795px)
|
||||
const marginTopPx = margins.top * 3.7795;
|
||||
const marginLeftPx = margins.left * 3.7795;
|
||||
const marginRightPx = margins.right * 3.7795;
|
||||
const marginBottomPx = margins.bottom * 3.7795;
|
||||
|
||||
// 캔버스 경계 (px)
|
||||
const canvasWidthPx = canvasWidth * 3.7795;
|
||||
const canvasHeightPx = canvasHeight * 3.7795;
|
||||
|
||||
// 드롭 위치 계산 (여백 내부로 제한)
|
||||
const rawX = x - 100;
|
||||
const rawY = y - 25;
|
||||
const minX = marginLeftPx;
|
||||
const minY = marginTopPx;
|
||||
const maxX = canvasWidthPx - marginRightPx - width;
|
||||
const maxY = canvasHeightPx - marginBottomPx - height;
|
||||
|
||||
const boundedX = Math.min(Math.max(minX, rawX), maxX);
|
||||
const boundedY = Math.min(Math.max(minY, rawY), maxY);
|
||||
|
||||
// 새 컴포넌트 생성 (Grid Snap 적용)
|
||||
const newComponent: ComponentConfig = {
|
||||
id: `comp_${uuidv4()}`,
|
||||
type: item.componentType,
|
||||
x: snapValueToGrid(Math.max(0, x - 100)),
|
||||
y: snapValueToGrid(Math.max(0, y - 25)),
|
||||
x: snapValueToGrid(boundedX),
|
||||
y: snapValueToGrid(boundedY),
|
||||
width: snapValueToGrid(width),
|
||||
height: snapValueToGrid(height),
|
||||
zIndex: components.length,
|
||||
|
|
@ -319,6 +341,19 @@ export function ReportDesignerCanvas() {
|
|||
}}
|
||||
onClick={handleCanvasClick}
|
||||
>
|
||||
{/* 페이지 여백 가이드 */}
|
||||
{currentPage && (
|
||||
<div
|
||||
className="pointer-events-none absolute border-2 border-dashed border-blue-300/50"
|
||||
style={{
|
||||
top: `${currentPage.margins.top}mm`,
|
||||
left: `${currentPage.margins.left}mm`,
|
||||
right: `${currentPage.margins.right}mm`,
|
||||
bottom: `${currentPage.margins.bottom}mm`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 정렬 가이드라인 렌더링 */}
|
||||
{alignmentGuides.vertical.map((x, index) => (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1352,61 +1352,6 @@ export function ReportDesignerRightPanel() {
|
|||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 배경색 */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm">배경</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div>
|
||||
<Label className="text-xs">배경색</Label>
|
||||
<div className="mt-1 flex gap-2">
|
||||
<Input
|
||||
type="color"
|
||||
value={currentPage.background_color}
|
||||
onChange={(e) =>
|
||||
updatePageSettings(currentPageId, {
|
||||
background_color: e.target.value,
|
||||
})
|
||||
}
|
||||
className="h-10 w-20"
|
||||
/>
|
||||
<Input
|
||||
type="text"
|
||||
value={currentPage.background_color}
|
||||
onChange={(e) =>
|
||||
updatePageSettings(currentPageId, {
|
||||
background_color: e.target.value,
|
||||
})
|
||||
}
|
||||
className="flex-1"
|
||||
placeholder="#ffffff"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 배경색 프리셋 */}
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{["#ffffff", "#f3f4f6", "#e5e7eb", "#d1d5db"].map((color) => (
|
||||
<button
|
||||
key={color}
|
||||
onClick={() =>
|
||||
updatePageSettings(currentPageId, {
|
||||
background_color: color,
|
||||
})
|
||||
}
|
||||
className="h-8 rounded border-2 transition-all hover:scale-110"
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderColor: currentPage.background_color === color ? "#3b82f6" : "#d1d5db",
|
||||
}}
|
||||
title={color}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
|
|
|
|||
Loading…
Reference in New Issue