Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev-ck
This commit is contained in:
commit
cebe226491
@ -30,6 +30,7 @@ import SettingsModal from './SettingsModal'
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import QPolygonContextMenu from '@/components/common/context-menu/QPolygonContextMenu'
|
import QPolygonContextMenu from '@/components/common/context-menu/QPolygonContextMenu'
|
||||||
import QLineContextMenu from '@/components/common/context-menu/QLineContextMenu'
|
import QLineContextMenu from '@/components/common/context-menu/QLineContextMenu'
|
||||||
|
import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMenu'
|
||||||
|
|
||||||
export default function Roof2(props) {
|
export default function Roof2(props) {
|
||||||
const { name, userId, email, isLoggedIn } = props
|
const { name, userId, email, isLoggedIn } = props
|
||||||
@ -588,7 +589,7 @@ export default function Roof2(props) {
|
|||||||
모드 DEFAULT
|
모드 DEFAULT
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" color={`${mode === Mode.DRAW_LINE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.DRAW_LINE)}>
|
<Button className="m-1 p-2" color={`${mode === Mode.DRAW_LINE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.DRAW_LINE)}>
|
||||||
기준선 긋기 모드
|
임의 그리드 모드
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" color={`${mode === Mode.EDIT ? 'primary' : 'default'}`} onClick={() => setMode(Mode.EDIT)}>
|
<Button className="m-1 p-2" color={`${mode === Mode.EDIT ? 'primary' : 'default'}`} onClick={() => setMode(Mode.EDIT)}>
|
||||||
에디팅모드
|
에디팅모드
|
||||||
@ -632,6 +633,9 @@ export default function Roof2(props) {
|
|||||||
<Button className="m-1 p-2" color={`${mode === Mode.TEXTBOX ? 'primary' : 'default'}`} onClick={() => setMode(Mode.TEXTBOX)}>
|
<Button className="m-1 p-2" color={`${mode === Mode.TEXTBOX ? 'primary' : 'default'}`} onClick={() => setMode(Mode.TEXTBOX)}>
|
||||||
텍스트박스 모드
|
텍스트박스 모드
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button className="m-1 p-2" color={`${mode === Mode.DRAW_RECT ? 'primary' : 'default'}`} onClick={() => setMode(Mode.DRAW_RECT)}>
|
||||||
|
도머 추가 모드
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="m-1 p-2"
|
className="m-1 p-2"
|
||||||
color={`${mode === Mode.ADSORPTION_POINT ? 'primary' : 'default'}`}
|
color={`${mode === Mode.ADSORPTION_POINT ? 'primary' : 'default'}`}
|
||||||
@ -753,7 +757,9 @@ export default function Roof2(props) {
|
|||||||
<ThumbnailList {...thumbnailProps} />
|
<ThumbnailList {...thumbnailProps} />
|
||||||
<div className="flex justify-start my-8 mx-2 w-full">
|
<div className="flex justify-start my-8 mx-2 w-full">
|
||||||
<canvas ref={canvasRef} id="canvas" style={{ border: '1px solid black' }} />
|
<canvas ref={canvasRef} id="canvas" style={{ border: '1px solid black' }} />
|
||||||
{!canvas ? null : currentObject?.type === 'QPolygon' ? (
|
{!canvas ? null : mode === Mode.DRAW_LINE ? (
|
||||||
|
<QEmptyContextMenu contextRef={canvasRef} canvasProps={canvas} />
|
||||||
|
) : currentObject?.type === 'QPolygon' ? (
|
||||||
<QPolygonContextMenu contextRef={canvasRef} canvasProps={canvas} />
|
<QPolygonContextMenu contextRef={canvasRef} canvasProps={canvas} />
|
||||||
) : currentObject?.type === 'QLine' ? (
|
) : currentObject?.type === 'QLine' ? (
|
||||||
<QLineContextMenu contextRef={canvasRef} canvasProps={canvas} />
|
<QLineContextMenu contextRef={canvasRef} canvasProps={canvas} />
|
||||||
|
|||||||
@ -56,7 +56,12 @@ export default function SettingsModal(props) {
|
|||||||
{
|
{
|
||||||
stroke: 'gray',
|
stroke: 'gray',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: true,
|
||||||
|
lockMovementX: true,
|
||||||
|
lockMovementY: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
name: 'guideLine',
|
name: 'guideLine',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -70,7 +75,12 @@ export default function SettingsModal(props) {
|
|||||||
{
|
{
|
||||||
stroke: 'gray',
|
stroke: 'gray',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: true,
|
||||||
|
lockMovementX: true,
|
||||||
|
lockMovementY: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
name: 'guideLine',
|
name: 'guideLine',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -137,7 +147,9 @@ export default function SettingsModal(props) {
|
|||||||
name: 'guideDot',
|
name: 'guideDot',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
canvasProps.add(backgroundPolygon)
|
canvasProps.add(backgroundPolygon)
|
||||||
|
backgroundPolygon.sendToBack()
|
||||||
canvasProps.renderAll()
|
canvasProps.renderAll()
|
||||||
|
|
||||||
const recoilObj = {
|
const recoilObj = {
|
||||||
|
|||||||
50
src/components/common/context-menu/QEmptyContextMenu.jsx
Normal file
50
src/components/common/context-menu/QEmptyContextMenu.jsx
Normal file
@ -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 <></>
|
||||||
|
}
|
||||||
@ -365,10 +365,13 @@ export function useMode() {
|
|||||||
canvas?.off('mouse:down')
|
canvas?.off('mouse:down')
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'drawLine':
|
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
|
break
|
||||||
case 'edit':
|
case 'edit':
|
||||||
canvas?.on('mouse:down', mouseEvent.editMode)
|
canvas?.on('mouse:down', mouseEvent.editMode)
|
||||||
|
|
||||||
break
|
break
|
||||||
case 'textbox':
|
case 'textbox':
|
||||||
canvas?.on('mouse:down', mouseEvent.textboxMode)
|
canvas?.on('mouse:down', mouseEvent.textboxMode)
|
||||||
@ -655,7 +658,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mouseEvent = {
|
const mouseEvent = {
|
||||||
drawLineMode: (options) => {
|
drawLineModeLeftClick: (options) => {
|
||||||
const pointer = canvas?.getPointer(options.e)
|
const pointer = canvas?.getPointer(options.e)
|
||||||
|
|
||||||
const line = new QLine(
|
const line = new QLine(
|
||||||
@ -672,6 +675,21 @@ export function useMode() {
|
|||||||
canvas?.add(line)
|
canvas?.add(line)
|
||||||
canvas?.renderAll()
|
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) => {
|
editMode: (options) => {
|
||||||
let pointer = canvas?.getPointer(options.e)
|
let pointer = canvas?.getPointer(options.e)
|
||||||
|
|
||||||
@ -802,31 +820,29 @@ export function useMode() {
|
|||||||
changeMode(canvas, Mode.EDIT)
|
changeMode(canvas, Mode.EDIT)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
drawRectMode: () => {
|
drawRectMode: (o) => {
|
||||||
let rect, isDown, origX, origY
|
let rect, isDown, origX, origY
|
||||||
canvas.on('mouse:down', function (o) {
|
isDown = true
|
||||||
isDown = true
|
const pointer = canvas.getPointer(o.e)
|
||||||
const pointer = canvas.getPointer(o.e)
|
origX = pointer.x
|
||||||
origX = pointer.x
|
origY = pointer.y
|
||||||
origY = pointer.y
|
rect = new fabric.Rect({
|
||||||
rect = new fabric.Rect({
|
left: origX,
|
||||||
left: origX,
|
top: origY,
|
||||||
top: origY,
|
originX: 'left',
|
||||||
originX: 'left',
|
originY: 'top',
|
||||||
originY: 'top',
|
width: pointer.x - origX,
|
||||||
width: pointer.x - origX,
|
height: pointer.y - origY,
|
||||||
height: pointer.y - origY,
|
angle: 0,
|
||||||
angle: 0,
|
fill: 'transparent',
|
||||||
fill: 'transparent',
|
stroke: 'black',
|
||||||
stroke: 'black',
|
transparentCorners: false,
|
||||||
transparentCorners: false,
|
|
||||||
})
|
|
||||||
canvas.add(rect)
|
|
||||||
})
|
})
|
||||||
|
canvas.add(rect)
|
||||||
|
|
||||||
canvas.on('mouse:move', function (o) {
|
canvas.on('mouse:move', function (e) {
|
||||||
if (!isDown) return
|
if (!isDown) return
|
||||||
const pointer = canvas.getPointer(o.e)
|
const pointer = canvas.getPointer(e.e)
|
||||||
if (origX > pointer.x) {
|
if (origX > pointer.x) {
|
||||||
rect.set({ left: Math.abs(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({ width: Math.abs(origX - pointer.x) })
|
||||||
rect.set({ height: Math.abs(origY - pointer.y) })
|
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) {
|
adsorptionPoint(o) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user