diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx
index 7467a634..2cfd6fae 100644
--- a/src/components/Roof2.jsx
+++ b/src/components/Roof2.jsx
@@ -11,6 +11,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import {
canvasSizeState,
compassState,
+ currentObjectState,
fontSizeState,
roofMaterialState,
roofState,
@@ -27,6 +28,8 @@ import QContextMenu from './common/context-menu/QContextMenu'
import { modalContent, modalState } from '@/store/modalAtom'
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'
export default function Roof2(props) {
const { name, userId, email, isLoggedIn } = props
@@ -67,6 +70,7 @@ export default function Roof2(props) {
const [contents, setContent] = useRecoilState(modalContent)
const [scale, setScale] = useState(1)
+ const currentObject = useRecoilValue(currentObjectState)
//canvas 썸네일
const [thumbnails, setThumbnails] = useState([])
@@ -126,6 +130,7 @@ export default function Roof2(props) {
if (canvas) {
const line = new QLine([50, 50, 200, 50], {
stroke: 'black',
+ selectable: true,
strokeWidth: 2,
fontSize: fontSize,
})
@@ -758,7 +763,13 @@ export default function Roof2(props) {
- {canvas !== undefined && }
+ {!canvas ? null : currentObject?.type === 'QPolygon' ? (
+
+ ) : currentObject?.type === 'QLine' ? (
+
+ ) : (
+
+ )}
>
)
diff --git a/src/components/common/context-menu/QLineContextMenu.jsx b/src/components/common/context-menu/QLineContextMenu.jsx
new file mode 100644
index 00000000..058c3b95
--- /dev/null
+++ b/src/components/common/context-menu/QLineContextMenu.jsx
@@ -0,0 +1,71 @@
+'use client'
+import { useEffect, useState } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
+
+export default function QLineContextMenu(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 (
+ <>
+ {contextMenu.visible && (
+
+
+ - handleMenuClick(1)}>
+ line
+
+ - handleMenuClick(1)}>
+ Option 1
+
+ - handleMenuClick(2)}>
+ Option 2
+
+ - handleMenuClick(3)}>
+ Option 3
+
+
+
+ )}
+ >
+ )
+}
diff --git a/src/components/common/context-menu/QPolygonContextMenu.jsx b/src/components/common/context-menu/QPolygonContextMenu.jsx
new file mode 100644
index 00000000..b3246165
--- /dev/null
+++ b/src/components/common/context-menu/QPolygonContextMenu.jsx
@@ -0,0 +1,71 @@
+'use client'
+import { useEffect, useState } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
+
+export default function QPolygonContextMenu(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 (
+ <>
+ {contextMenu.visible && (
+
+
+ - handleMenuClick(1)}>
+ polygon
+
+ - handleMenuClick(1)}>
+ Option 1
+
+ - handleMenuClick(2)}>
+ Option 2
+
+ - handleMenuClick(3)}>
+ Option 3
+
+
+
+ )}
+ >
+ )
+}
diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js
index 1947708f..ea5256e6 100644
--- a/src/hooks/useCanvasEvent.js
+++ b/src/hooks/useCanvasEvent.js
@@ -1,11 +1,12 @@
import { useEffect, useState } from 'react'
import { fabric } from 'fabric'
-import { useRecoilValue } from 'recoil'
-import { canvasSizeState, modeState } from '@/store/canvasAtom'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { canvasSizeState, currentObjectState, modeState } from '@/store/canvasAtom'
// 캔버스에 필요한 이벤트
export function useCanvasEvent() {
const [canvas, setCanvasForEvent] = useState(null)
+ const [currentObject, setCurrentObject] = useRecoilState(currentObjectState)
const canvasSize = useRecoilValue(canvasSizeState)
// 기본적인 이벤트 필요시 추가
@@ -15,11 +16,28 @@ export function useCanvasEvent() {
canvas?.on('object:added', addEventOnObject)
canvas?.on('object:modified', onChange)
canvas?.on('object:removed', onChange)
+ canvas?.on('selection:cleared', selectionEvent.cleared)
+ canvas?.on('selection:created', selectionEvent.created)
+ canvas?.on('selection:updated', selectionEvent.updated)
canvas?.on('object:added', () => {
document.addEventListener('keydown', handleKeyDown)
})
}
+ const selectionEvent = {
+ created: (e) => {
+ const target = e.selected[0]
+ setCurrentObject(target)
+ },
+ cleared: (e) => {
+ setCurrentObject(null)
+ },
+ updated: (e) => {
+ const target = e.selected[0]
+ setCurrentObject(target)
+ },
+ }
+
const onChange = (e) => {
const target = e.target
if (target) {
@@ -32,8 +50,9 @@ export function useCanvasEvent() {
canvas?.off('object:modified')
canvas?.off('object:removed')
canvas?.off('object:added')
- canvas?.off('mouse:move')
- canvas?.off('mouse:down')
+ canvas?.off('selection:cleared')
+ canvas?.off('selection:created')
+ canvas?.off('selection:updated')
}
const addEventOnObject = (e) => {
diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js
index 062698c0..fafe26a1 100644
--- a/src/store/canvasAtom.js
+++ b/src/store/canvasAtom.js
@@ -94,3 +94,9 @@ export const guideLineState = atom({
default: {},
dangerouslyAllowMutability: true,
})
+
+export const currentObjectState = atom({
+ key: 'currentObject',
+ default: null,
+ dangerouslyAllowMutability: true,
+})