diff --git a/frontend/components/report/designer/CanvasComponent.tsx b/frontend/components/report/designer/CanvasComponent.tsx index 1329f847..238b79a9 100644 --- a/frontend/components/report/designer/CanvasComponent.tsx +++ b/frontend/components/report/designer/CanvasComponent.tsx @@ -7,6 +7,9 @@ import { getFullImageUrl } from "@/lib/api/client"; import JsBarcode from "jsbarcode"; import QRCode from "qrcode"; +// 고정 스케일 팩터 (화면 해상도와 무관) +const MM_TO_PX = 4; + // 1D 바코드 렌더러 컴포넌트 interface BarcodeRendererProps { value: string; @@ -252,15 +255,15 @@ export function CanvasComponent({ component }: CanvasComponentProps) { const newX = Math.max(0, e.clientX - dragStart.x); const newY = Math.max(0, e.clientY - dragStart.y); - // 여백을 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; + // 여백을 px로 변환 + const marginTopPx = margins.top * MM_TO_PX; + const marginBottomPx = margins.bottom * MM_TO_PX; + const marginLeftPx = margins.left * MM_TO_PX; + const marginRightPx = margins.right * MM_TO_PX; // 캔버스 경계 체크 (mm를 px로 변환) - const canvasWidthPx = canvasWidth * 3.7795; - const canvasHeightPx = canvasHeight * 3.7795; + const canvasWidthPx = canvasWidth * MM_TO_PX; + const canvasHeightPx = canvasHeight * MM_TO_PX; // 컴포넌트가 여백 안에 있도록 제한 const minX = marginLeftPx; @@ -312,12 +315,12 @@ export function CanvasComponent({ component }: CanvasComponentProps) { const newHeight = Math.max(30, resizeStart.height + deltaY); // 여백을 px로 변환 - const marginRightPx = margins.right * 3.7795; - const marginBottomPx = margins.bottom * 3.7795; + const marginRightPx = margins.right * MM_TO_PX; + const marginBottomPx = margins.bottom * MM_TO_PX; // 캔버스 경계 체크 - const canvasWidthPx = canvasWidth * 3.7795; - const canvasHeightPx = canvasHeight * 3.7795; + const canvasWidthPx = canvasWidth * MM_TO_PX; + const canvasHeightPx = canvasHeight * MM_TO_PX; // 컴포넌트가 여백을 벗어나지 않도록 최대 크기 제한 const maxWidth = canvasWidthPx - marginRightPx - component.x; diff --git a/frontend/components/report/designer/ReportDesignerCanvas.tsx b/frontend/components/report/designer/ReportDesignerCanvas.tsx index 08bf9c1b..f278cd97 100644 --- a/frontend/components/report/designer/ReportDesignerCanvas.tsx +++ b/frontend/components/report/designer/ReportDesignerCanvas.tsx @@ -8,6 +8,10 @@ import { CanvasComponent } from "./CanvasComponent"; import { Ruler } from "./Ruler"; import { v4 as uuidv4 } from "uuid"; +// mm를 px로 변환하는 고정 스케일 팩터 (화면 해상도와 무관하게 일정) +// A4 기준: 210mm x 297mm → 840px x 1188px +export const MM_TO_PX = 4; + export function ReportDesignerCanvas() { const canvasRef = useRef(null); const { @@ -76,15 +80,15 @@ export function ReportDesignerCanvas() { height = 30; } - // 여백을 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 marginTopPx = margins.top * MM_TO_PX; + const marginLeftPx = margins.left * MM_TO_PX; + const marginRightPx = margins.right * MM_TO_PX; + const marginBottomPx = margins.bottom * MM_TO_PX; // 캔버스 경계 (px) - const canvasWidthPx = canvasWidth * 3.7795; - const canvasHeightPx = canvasHeight * 3.7795; + const canvasWidthPx = canvasWidth * MM_TO_PX; + const canvasHeightPx = canvasHeight * MM_TO_PX; // 드롭 위치 계산 (여백 내부로 제한) const rawX = x - 100; @@ -402,8 +406,8 @@ export function ReportDesignerCanvas() { }} className={`relative bg-white shadow-lg ${isOver ? "ring-2 ring-blue-500" : ""}`} style={{ - width: `${canvasWidth}mm`, - minHeight: `${canvasHeight}mm`, + width: `${canvasWidth * MM_TO_PX}px`, + minHeight: `${canvasHeight * MM_TO_PX}px`, backgroundImage: showGrid ? ` linear-gradient(to right, #e5e7eb 1px, transparent 1px), @@ -419,10 +423,10 @@ export function ReportDesignerCanvas() {
)} diff --git a/frontend/components/report/designer/Ruler.tsx b/frontend/components/report/designer/Ruler.tsx index 6f2dc1a2..e293c593 100644 --- a/frontend/components/report/designer/Ruler.tsx +++ b/frontend/components/report/designer/Ruler.tsx @@ -8,9 +8,12 @@ interface RulerProps { offset?: number; // 스크롤 오프셋 (px) } +// 고정 스케일 팩터 (화면 해상도와 무관) +const MM_TO_PX = 4; + export function Ruler({ orientation, length, offset = 0 }: RulerProps) { - // mm를 px로 변환 (1mm = 3.7795px, 96dpi 기준) - const mmToPx = (mm: number) => mm * 3.7795; + // mm를 px로 변환 + const mmToPx = (mm: number) => mm * MM_TO_PX; const lengthPx = mmToPx(length); const isHorizontal = orientation === "horizontal"; diff --git a/frontend/contexts/ReportDesignerContext.tsx b/frontend/contexts/ReportDesignerContext.tsx index 324c0847..206f56db 100644 --- a/frontend/contexts/ReportDesignerContext.tsx +++ b/frontend/contexts/ReportDesignerContext.tsx @@ -803,9 +803,10 @@ export function ReportDesignerProvider({ reportId, children }: { reportId: strin const horizontalLines: number[] = []; const threshold = 5; // 5px 오차 허용 - // 캔버스를 픽셀로 변환 (1mm = 3.7795px) - const canvasWidthPx = canvasWidth * 3.7795; - const canvasHeightPx = canvasHeight * 3.7795; + // 캔버스를 픽셀로 변환 (고정 스케일 팩터: 1mm = 4px) + const MM_TO_PX = 4; + const canvasWidthPx = canvasWidth * MM_TO_PX; + const canvasHeightPx = canvasHeight * MM_TO_PX; const canvasCenterX = canvasWidthPx / 2; const canvasCenterY = canvasHeightPx / 2;