diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 794c0265..ed2e837f 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -30,6 +30,7 @@ import SettingsModal from './SettingsModal' import { useAxios } from '@/hooks/useAxios' import QPolygonContextMenu from '@/components/common/context-menu/QPolygonContextMenu' import QLineContextMenu from '@/components/common/context-menu/QLineContextMenu' +import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMenu' export default function Roof2(props) { const { name, userId, email, isLoggedIn } = props @@ -588,7 +589,7 @@ export default function Roof2(props) { 모드 DEFAULT setMode(Mode.DRAW_LINE)}> - 기준선 긋기 모드 + 임의 그리드 모드 setMode(Mode.EDIT)}> 에디팅모드 @@ -632,6 +633,9 @@ export default function Roof2(props) { setMode(Mode.TEXTBOX)}> 텍스트박스 모드 + setMode(Mode.DRAW_RECT)}> + 도머 추가 모드 + - {!canvas ? null : currentObject?.type === 'QPolygon' ? ( + {!canvas ? null : mode === Mode.DRAW_LINE ? ( + + ) : currentObject?.type === 'QPolygon' ? ( ) : currentObject?.type === 'QLine' ? ( diff --git a/src/components/SettingsModal.jsx b/src/components/SettingsModal.jsx index 2ae6fae6..3cf9997b 100644 --- a/src/components/SettingsModal.jsx +++ b/src/components/SettingsModal.jsx @@ -56,7 +56,12 @@ export default function SettingsModal(props) { { stroke: 'gray', strokeWidth: 1, - selectable: false, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, name: 'guideLine', }, ) @@ -70,7 +75,12 @@ export default function SettingsModal(props) { { stroke: 'gray', strokeWidth: 1, - selectable: false, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, name: 'guideLine', }, ) @@ -137,7 +147,9 @@ export default function SettingsModal(props) { name: 'guideDot', }, ) + canvasProps.add(backgroundPolygon) + backgroundPolygon.sendToBack() canvasProps.renderAll() const recoilObj = { diff --git a/src/components/common/context-menu/QEmptyContextMenu.jsx b/src/components/common/context-menu/QEmptyContextMenu.jsx new file mode 100644 index 00000000..c4734fc4 --- /dev/null +++ b/src/components/common/context-menu/QEmptyContextMenu.jsx @@ -0,0 +1,50 @@ +'use client' +import { useEffect, useState } from 'react' +import { useRecoilState, useRecoilValue } from 'recoil' + +export default function QEmptyContextMenu(props) { + const { contextRef, canvasProps } = props + + // const children = useRecoilValue(modalContent) + const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 }) + + useEffect(() => { + if (!contextRef.current) return + + const handleContextMenu = (e) => { + e.preventDefault() //기존 contextmenu 막고 + setContextMenu({ visible: true, x: e.pageX, y: e.pageY }) + canvasProps.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제 + } + + const handleClick = (e) => { + e.preventDefault() + setContextMenu({ ...contextMenu, visible: false }) + } + + const handleOutsideClick = (e) => { + e.preventDefault() + if (contextMenu.visible && !ref.current.contains(e.target)) { + setContextMenu({ ...contextMenu, visible: false }) + } + } + + // Prevent the default context menu from appearing on the canvas + canvasProps.upperCanvasEl.addEventListener('contextmenu', handleContextMenu) + document.addEventListener('click', handleClick) + document.addEventListener('click', handleOutsideClick) + + return () => { + // canvasProps.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) + document.removeEventListener('click', handleClick) + document.removeEventListener('click', handleOutsideClick) + } + }, [contextRef, contextMenu]) + + const handleMenuClick = (option) => { + alert(`option ${option} clicked`) + setContextMenu({ ...contextMenu, visible: false }) + } + + return <>> +} diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 5666dabd..ae970461 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -365,10 +365,13 @@ export function useMode() { canvas?.off('mouse:down') switch (mode) { case 'drawLine': - canvas?.on('mouse:down', mouseEvent.drawLineMode) + canvas?.on('mouse:down', mouseEvent.drawLineModeLeftClick) + window.document.removeEventListener('contextmenu', mouseEvent.drawLineModeRightClick) + window.document.addEventListener('contextmenu', mouseEvent.drawLineModeRightClick) break case 'edit': canvas?.on('mouse:down', mouseEvent.editMode) + break case 'textbox': canvas?.on('mouse:down', mouseEvent.textboxMode) @@ -655,7 +658,7 @@ export function useMode() { } const mouseEvent = { - drawLineMode: (options) => { + drawLineModeLeftClick: (options) => { const pointer = canvas?.getPointer(options.e) const line = new QLine( @@ -672,6 +675,21 @@ export function useMode() { canvas?.add(line) canvas?.renderAll() }, + drawLineModeRightClick: (options) => { + const line = new fabric.Line( + [0, options.offsetY, canvas.width, options.offsetY], // y축에 1자 선을 그립니다. + { + stroke: 'black', + strokeWidth: 2, + viewLengthText: true, + selectable: false, + fontSize: fontSize, + }, + ) + + canvas?.add(line) + canvas?.renderAll() + }, editMode: (options) => { let pointer = canvas?.getPointer(options.e) @@ -802,31 +820,29 @@ export function useMode() { changeMode(canvas, Mode.EDIT) }) }, - drawRectMode: () => { + drawRectMode: (o) => { let rect, isDown, origX, origY - canvas.on('mouse:down', function (o) { - isDown = true - const pointer = canvas.getPointer(o.e) - origX = pointer.x - origY = pointer.y - rect = new fabric.Rect({ - left: origX, - top: origY, - originX: 'left', - originY: 'top', - width: pointer.x - origX, - height: pointer.y - origY, - angle: 0, - fill: 'transparent', - stroke: 'black', - transparentCorners: false, - }) - canvas.add(rect) + isDown = true + const pointer = canvas.getPointer(o.e) + origX = pointer.x + origY = pointer.y + rect = new fabric.Rect({ + left: origX, + top: origY, + originX: 'left', + originY: 'top', + width: pointer.x - origX, + height: pointer.y - origY, + angle: 0, + fill: 'transparent', + stroke: 'black', + transparentCorners: false, }) + canvas.add(rect) - canvas.on('mouse:move', function (o) { + canvas.on('mouse:move', function (e) { if (!isDown) return - const pointer = canvas.getPointer(o.e) + const pointer = canvas.getPointer(e.e) if (origX > pointer.x) { rect.set({ left: Math.abs(pointer.x) }) } @@ -837,6 +853,13 @@ export function useMode() { rect.set({ width: Math.abs(origX - pointer.x) }) rect.set({ height: Math.abs(origY - pointer.y) }) }) + + canvas.on('mouse:up', function (o) { + isDown = false + canvas.off('mouse:move') + canvas.off('mouse:up') + setMode(Mode.DEFAULT) + }) }, // 흡착점 추가 adsorptionPoint(o) {