마우스 contextmenu 구현

This commit is contained in:
yjnoh 2024-08-21 17:57:41 +09:00
parent 7460409802
commit 7e68be16a1
5 changed files with 77 additions and 12 deletions

View File

@ -1,6 +1,6 @@
NEXT_PUBLIC_TEST="테스트변수입니다. development"
NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080"
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"

View File

@ -1,5 +1,5 @@
import { useCanvas } from '@/hooks/useCanvas'
import { useEffect, useState } from 'react'
import { useEffect, useState, useRef } from 'react'
import { Mode, useMode } from '@/hooks/useMode'
import { Button } from '@nextui-org/react'
import RangeSlider from './ui/RangeSlider'
@ -19,10 +19,13 @@ import { getCanvasState, insertCanvasState } from '@/lib/canvas'
import { calculateIntersection } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import ThumbnailList from './ui/ThumbnailLIst'
import CanvasWithContextMenu from '@/util/context-util'
export default function Roof2() {
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
const canvasRef = useRef(null)
//canvas
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
@ -699,7 +702,8 @@ export default function Roof2() {
)}
<ThumbnailList {...thumbnailProps} />
<div className="flex justify-start my-8 mx-2 w-full">
<canvas id="canvas" style={{ border: '1px solid black' }} />
<canvas ref={canvasRef} id="canvas" style={{ border: '1px solid black' }} />
{canvas !== undefined && <CanvasWithContextMenu ref={canvasRef} canvasProps={canvas} />}
</div>
</>
)

View File

@ -64,15 +64,11 @@ export function useCanvas(id) {
useEffect(() => {
if (canvas) {
initialize()
canvas?.on('object:added', onChange)
canvas?.on('object:added', addEventOnObject)
canvas?.on('object:modified', onChange)
canvas?.on('object:removed', onChange)
canvas?.on('mouse:move', drawMouseLines)
canvas?.on('mouse:out', removeMouseLines)
removeEventOnCanvas()
addEventOnCanvas()
}
}, [canvas])
const addEventOnCanvas = () => {
canvas?.on('object:added', onChange)
canvas?.on('object:modified', onChange)

View File

@ -277,7 +277,7 @@ export function useMode() {
break
case 'default':
canvas?.off('mouse:down')
// canvas?.off('mouse:down')
break
}
}
@ -510,7 +510,7 @@ export function useMode() {
setMode(mode)
// mode변경 시 이전 이벤트 제거
setCanvas(canvas)
canvas?.off('mouse:down')
// canvas?.off('mouse:down')
addEvent(mode)
}

65
src/util/context-util.js Normal file
View File

@ -0,0 +1,65 @@
import React, { useState, useEffect, forwardRef, useContext } from 'react'
const CanvasWithContextMenu = forwardRef(({ canvasProps }, ref) => {
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
useEffect(() => {
if (!ref.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)
}
}, [ref, contextMenu])
const handleMenuClick = (option) => {
alert(`option ${option} clicked`)
setContextMenu({ ...contextMenu, visible: false })
}
return (
<>
{contextMenu.visible && (
<div style={{ position: 'absolute', top: contextMenu.y, left: contextMenu.x, zIndex: 2000 }}>
<ul style={{ listStyle: 'none', margin: 0, padding: '5px' }}>
<li style={{ padding: '8px 12px', cursor: 'pointer' }} onClick={() => handleMenuClick(1)}>
Option 1
</li>
<li style={{ padding: '8px 12px', cursor: 'pointer' }} onClick={() => handleMenuClick(2)}>
Option 2
</li>
<li style={{ padding: '8px 12px', cursor: 'pointer' }} onClick={() => handleMenuClick(3)}>
Option 3
</li>
</ul>
</div>
)}
</>
)
})
export default CanvasWithContextMenu