Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
yoosangwook 2024-09-20 18:16:40 +09:00
commit 1430b187fa
8 changed files with 303 additions and 97 deletions

View File

@ -12,7 +12,7 @@ export default function QContextMenu(props) {
let contextType = ''
if (activeObject) {
if (activeObject.initOptions) {
if (activeObject.initOptions && activeObject.initOptions.name) {
//
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
contextType = 'surface' //

View File

@ -4,20 +4,34 @@ import { useEffect, useState } from 'react'
import MenuDepth01 from './MenuDepth01'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useMessage } from '@/hooks/useMessage'
import { post } from '@/lib/Axios'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { canvasZoomState, verticalHorizontalModeState } from '@/store/canvasAtom'
import { canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
import { outerLinePointsState } from '@/store/outerLineAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { MENU } from '@/common/common'
import { useAxios } from '@/hooks/useAxios'
import { toastUp } from '@/hooks/useToast'
import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json'
export default function CanvasMenu(props) {
const [objectNo] = useState('test123240912001') //
const [objectNo, setObjectNo] = useState('test123240912001') //
const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
const [menuNumber, setMenuNumber] = useState(null)
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
const [vertical, setVertical] = useState(true)
const [type, setType] = useState('')
const { getMessage } = useMessage()
const canvasZoom = useRecoilValue(canvasZoomState)
const canvas = useRecoilValue(canvasState)
const setCurrentMenu = useSetRecoilState(currentMenuState)
const setPoints = useSetRecoilState(outerLinePointsState)
const globalLocale = useRecoilValue(globalLocaleStore)
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
const { post } = useAxios()
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
const onClickNav = (number) => {
setMenuNumber(number)
@ -33,7 +47,13 @@ export default function CanvasMenu(props) {
const firstOptions = useRecoilState(settingModalFirstOptionsState)
const secondOptions = useRecoilState(settingModalSecondOptionsState)
useEffect(() => {}, [menuNumber, type])
useEffect(() => {
if (globalLocale === 'ko') {
setAppMessageState(KO)
} else {
setAppMessageState(JA)
}
}, [menuNumber, type, globalLocale])
// (btn08)
const handleSaveSettings = async () => {
@ -60,6 +80,7 @@ export default function CanvasMenu(props) {
const patternData = {
objectNo,
// ()
assignDisplay: dataToSend.firstOption1[0].selected,
drawDisplay: dataToSend.firstOption1[1].selected,
gridDisplay: dataToSend.firstOption1[2].selected,
@ -71,9 +92,11 @@ export default function CanvasMenu(props) {
trestleDisplay: dataToSend.firstOption1[8].selected,
coordiDisplay: dataToSend.firstOption1[9].selected,
drawConverDisplay: dataToSend.firstOption1[10].selected,
// ()
onlyBorder: dataToSend.firstOption2[0].selected,
lineHatch: dataToSend.firstOption2[1].selected,
allPainted: dataToSend.firstOption2[2].selected,
// ()
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
@ -81,16 +104,19 @@ export default function CanvasMenu(props) {
}
// HTTP POST
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
//
alert('설정이 저장되었습니다.')
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
toastUp({ message: res.returnMessage, type: 'success' })
})
} catch (error) {
console.error('설정을 저장하는 동안 오류가 발생했습니다:', error)
alert('설정을 저장하는 중 오류가 발생했습니다.')
toastUp({ message: res.returnMessage, type: 'error' })
}
}
const handleClear = () => {
setPoints([])
canvas?.clear()
}
return (
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
<div className="canvas-menu-inner">
@ -111,6 +137,7 @@ export default function CanvasMenu(props) {
className={`canvas-menu-item ${menuNumber === 2 ? 'active' : ''}`}
onClick={() => {
onClickNav(2)
setCurrentMenu(MENU.ROOF_COVERING.DEFAULT)
}}
>
<button>
@ -118,25 +145,49 @@ export default function CanvasMenu(props) {
{getMessage('plan.menu.roof.cover')}
</button>
</li>
<li className={`canvas-menu-item ${menuNumber === 3 ? 'active' : ''}`} onClick={() => onClickNav(3)}>
<li
className={`canvas-menu-item ${menuNumber === 3 ? 'active' : ''}`}
onClick={() => {
onClickNav(3)
setCurrentMenu(MENU.BATCH_CANVAS.DEFAULT)
}}
>
<button>
<span className="menu-icon con03"></span>
{getMessage('plan.menu.placement.surface')}
</button>
</li>
<li className={`canvas-menu-item ${menuNumber === 4 ? 'active' : ''}`} onClick={() => onClickNav(4)}>
<li
className={`canvas-menu-item ${menuNumber === 4 ? 'active' : ''}`}
onClick={() => {
onClickNav(4)
setCurrentMenu(MENU.MODULE_CIRCUIT_SETTING.DEFAULT)
}}
>
<button>
<span className="menu-icon con04"></span>
{getMessage('plan.menu.module.circuit.setting')}
</button>
</li>
<li className={`canvas-menu-item ${menuNumber === 5 ? 'active' : ''}`} onClick={() => onClickNav(5)}>
<li
className={`canvas-menu-item ${menuNumber === 5 ? 'active' : ''}`}
onClick={() => {
onClickNav(5)
setCurrentMenu(MENU.ESTIMATE.DEFAULT)
}}
>
<button>
<span className="menu-icon con06"></span>
{getMessage('plan.menu.estimate')}
</button>
</li>
<li className={`canvas-menu-item ${menuNumber === 6 ? 'active' : ''}`} onClick={() => onClickNav(6)}>
<li
className={`canvas-menu-item ${menuNumber === 6 ? 'active' : ''}`}
onClick={() => {
onClickNav(6)
setCurrentMenu(MENU.POWER_GENERATION_SIMULATION.DEFAULT)
}}
>
<button>
<span className="menu-icon con05"></span>
{getMessage('plan.menu.simulation')}
@ -171,7 +222,7 @@ export default function CanvasMenu(props) {
<button className="control-btn plus"></button>
</div>
<div className="btn-from">
<button className="btn07"></button>
<button className="btn07" onClick={handleClear}></button>
<button className="btn08" onClick={handleSaveSettings}></button>
<button className="btn09"></button>
</div>

View File

@ -3,14 +3,19 @@
import { ToggleonMouse } from '@/components/header/Header'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
import { MENU } from '@/common/common'
import { currentMenuState } from '@/store/canvasAtom'
import { useSetRecoilState } from 'recoil'
export default function MenuDepth01(props) {
const { setShowOutlineModal, type } = props
const { getMessage } = useMessage()
const [activeMenu, setActiveMenu] = useState()
const onClickMenu = (menuNum) => {
setActiveMenu(menuNum)
setShowOutlineModal(menuNum === 0)
const setCurrentMenu = useSetRecoilState(currentMenuState)
const onClickMenu = ({ id, menu, name }) => {
setActiveMenu(menu)
setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
setCurrentMenu(menu)
}
const menus = [
@ -26,21 +31,21 @@ export default function MenuDepth01(props) {
const menuInfo = {
outline: [
//
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing' },
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting' },
{ id: 2, name: 'plan.menu.roof.cover.roof.shape.edit' },
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing' },
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
{ id: 2, name: 'plan.menu.roof.cover.roof.shape.edit', menu: MENU.ROOF_COVERING.ROOF_SHAPE_EDITING },
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
],
surface: [
//
{ id: 0, name: 'plan.menu.placement.surface.drawing' },
{ id: 1, name: 'plan.menu.placement.surface.surface' },
{ id: 2, name: 'plan.menu.placement.surface.object' },
{ id: 0, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
{ id: 1, name: 'plan.menu.placement.surface.surface', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
{ id: 2, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
],
module: [
// ,
{ id: 0, name: 'plan.menu.module.circuit.setting.default' },
{ id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting' },
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
{ id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting', menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING },
],
}
@ -54,8 +59,8 @@ export default function MenuDepth01(props) {
<ul className="canvas-depth2-list">
{menuInfo[type].map((menu) => {
return (
<li key={menu.id} className={`canvas-depth2-item ${menu.id === activeMenu ? 'active' : ''}`}>
<button onClick={() => onClickMenu(menu.id)}>{getMessage(menu.name)}</button>
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}>
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
</li>
)
})}

View File

@ -8,6 +8,7 @@ import { useEvent } from '@/hooks/useEvent'
import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
import {
OUTER_LINE_TYPE,
outerLineAngle1State,
outerLineArrow1State,
outerLineArrow2State,
outerLineLength1State,
@ -18,16 +19,19 @@ import {
import { QLine } from '@/components/fabric/QLine'
import { useLine } from '@/hooks/useLine'
import { distanceBetweenPoints } from '@/util/canvas-util'
import { calculateAngle } from '@/util/qpolygon-utils'
export default function OuterLineWall(props) {
const { setShowOutlineModal } = props
const { getMessage } = useMessage()
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent()
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
useEvent()
const { addLineText, removeLineText } = useLine()
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
const length1Ref = useRef(null)
const length2Ref = useRef(null)
const angle1Ref = useRef(null)
const [length1, setLength1] = useRecoilState(outerLineLength1State)
const [length2, setLength2] = useRecoilState(outerLineLength2State)
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
@ -37,11 +41,16 @@ export default function OuterLineWall(props) {
const arrow1Ref = useRef(arrow1)
const arrow2Ref = useRef(arrow2)
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
const canvas = useRecoilValue(canvasState)
useEffect(() => {
removeAllMouseEventListeners()
removeMouseEvent('mouse:down', mouseDown)
addCanvasMouseEventListener('mouse:down', mouseDown)
return () => {
removeAllMouseEventListeners()
}
}, [verticalHorizontalMode, points])
useEffect(() => {
@ -164,6 +173,24 @@ export default function OuterLineWall(props) {
}
if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
let isAllRightAngle = true
const firstPoint = points[0]
points.forEach((point, idx) => {
if (idx === 0 || !isAllRightAngle) {
return
}
const angle = calculateAngle(point, firstPoint)
if (angle % 90 !== 0) {
isAllRightAngle = false
}
})
if (isAllRightAngle) {
return
}
const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
@ -423,7 +450,25 @@ export default function OuterLineWall(props) {
console.log('leegubae')
},
angle: (e) => {
console.log('angle')
const key = e.key
switch (key) {
case 'Enter': {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
const lastPoint = prev[prev.length - 1]
const length = length1Ref.current.value / 10
const angle = angle1Ref.current.value
//lastPoint angle1 length1
const radian = (angle * Math.PI) / 180
const x = lastPoint.x + length * Math.cos(radian)
const y = lastPoint.y - length * Math.sin(radian)
return [...prev, { x, y }]
})
}
}
},
diagonalLine: (e) => {
console.log('diagonalLine')
@ -442,6 +487,27 @@ export default function OuterLineWall(props) {
if (points.length < 3) {
return
}
let isAllRightAngle = true
const firstPoint = points[0]
points.forEach((point, idx) => {
if (idx === 0 || !isAllRightAngle) {
return
}
const angle = calculateAngle(point, firstPoint)
if (angle % 90 !== 0) {
isAllRightAngle = false
}
})
if (isAllRightAngle) {
alert('부정확한 다각형입니다.')
return
}
setPoints((prev) => {
if (prev.length === 0) {
return []
@ -449,6 +515,7 @@ export default function OuterLineWall(props) {
return [...prev, { x: prev[0].x, y: prev[0].y }]
})
}
return (
<WithDraggable isShow={true} pos={{ x: 50, y: -1000 + 50 }}>
<div className={`modal-pop-wrap ssm`}>
@ -501,7 +568,8 @@ export default function OuterLineWall(props) {
value={length1}
ref={length1Ref}
onChange={(e) => {
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
const value = e.target.value.replace(/^0+/, '')
setLength1(value.replace(/[^-0-9]/g, ''))
}}
placeholder="3000"
/>
@ -521,7 +589,8 @@ export default function OuterLineWall(props) {
value={length1}
ref={length1Ref}
onChange={(e) => {
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
const value = e.target.value.replace(/^0+/, '')
setLength1(value.replace(/[^-0-9]/g, ''))
}}
placeholder="3000"
/>
@ -538,7 +607,8 @@ export default function OuterLineWall(props) {
value={length2}
ref={length2Ref}
onChange={(e) => {
setLength2(e.target.value.replace(/[^-0-9]/g, ''))
const value = e.target.value.replace(/^0+/, '')
setLength2(value.replace(/[^-0-9]/g, ''))
}}
placeholder="3000"
/>
@ -548,6 +618,44 @@ export default function OuterLineWall(props) {
<input type="text" readOnly={true} value={arrow2} className="input-origin block" />
</div>
</div>
) : type === OUTER_LINE_TYPE.ANGLE ? (
<div className="outer-line-wrap">
<div className="form-input">
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
<input
type="text"
className="input-origin block"
value={length1}
ref={length1Ref}
onChange={(e) => {
const value = e.target.value.replace(/^0+/, '')
setLength1(value.replace(/[^-0-9]/g, ''))
}}
placeholder="3000"
/>
</div>
<div className="form-input">
<label htmlFor="">{getMessage('modal.cover.outline.angle')}</label>
<input
type="text"
value={angle1}
ref={angle1Ref}
onChange={(e) => {
const val = e.target.value
// const pattern = /(^\d+$)|(^\d{1,}.\d{0,2}$)/
const pattern = /^-?(\d{1,3}([.]\d{0,2})?)?$/
if (!pattern.test(val)) {
// prev
setAngle1(val.slice(0, val.length - 1))
return
}
setAngle1(val)
}}
className="input-origin block"
/>
</div>
</div>
) : (
<></>
)}

View File

@ -1,28 +1,24 @@
import { useRecoilState } from 'recoil'
import { settingModalFirstOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react'
import { get } from '@/lib/Axios'
import React, { useCallback, useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios'
export default function FirstOption() {
const [objectNo] = useState('test123240912001') //
const [objectNo, setObjectNo] = useState('test123240912001') //
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
const { option1, option2 } = settingsModalOptions
const { getMessage } = useMessage()
const [isFetched, setIsFetched] = useState(false) //
const { get } = useAxios()
//
useEffect(() => {
console.log('FirstOption useEffect 실행')
if (!isFetched) {
// fetchSettings
fetchSettings()
}
}, [isFetched]) // isFetched
fetchSettings()
}, [objectNo])
// Canvas Setting
const fetchSettings = async () => {
const fetchSettings = useCallback(async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
@ -49,12 +45,10 @@ export default function FirstOption() {
option1,
option2,
})
setIsFetched(true) // isFetched true
} catch (error) {
console.error('Data fetching error:', error)
}
}
}, [objectNo])
const onClickOption = (option) => {
option.selected = !option.selected
@ -67,23 +61,25 @@ export default function FirstOption() {
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title light">{getMessage('modal.canvas.setting.first.option.info')}</h3>
<div className="flex-check-box for2">
{settingsModalOptions?.option1?.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
{settingsModalOptions &&
settingsModalOptions.option1.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
</div>
</div>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.first.option.display')}</h3>
<div className="flex-check-box for-line">
{settingsModalOptions?.option2?.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
{settingsModalOptions &&
settingsModalOptions.option2.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
</div>
</div>
</>

View File

@ -1,27 +1,24 @@
import { useRecoilState } from 'recoil'
import { settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react'
import { get } from '@/lib/Axios'
import React, { useCallback, useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios'
export default function SecondOption() {
const [objectNo] = useState('test123240912001') //
const [objectNo, setObjectNo] = useState('test123240912001') //
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
const { option1, option2 } = settingsModalOptions
const { getMessage } = useMessage()
const [isFetched, setIsFetched] = useState(false) //
const { get } = useAxios()
//
useEffect(() => {
console.log('SecondOption useEffect 실행')
if (!isFetched) {
// fetchSettings
fetchSettings()
}
}, [isFetched]) // isFetched
fetchSettings()
}, [objectNo])
const fetchSettings = async () => {
// Canvas Setting
const fetchSettings = useCallback(async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
@ -36,12 +33,10 @@ export default function SecondOption() {
option1,
option2,
})
setIsFetched(true) // isFetched true
} catch (error) {
console.error('Data fetching error:', error)
}
}
}, [objectNo])
const onClickOption = (option) => {
// option2
@ -54,22 +49,24 @@ export default function SecondOption() {
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.edit')}</h3>
<div className="flex-check-box for2">
{settingsModalOptions.option1.map((item, index) => (
<button key={item.id || index} className="arr-btn">
<span>{getMessage(item.name)}</span>
</button>
))}
{settingsModalOptions &&
settingsModalOptions.option1.map((item) => (
<button key={item.id} className="arr-btn">
<span>{getMessage(item.name)}</span>
</button>
))}
</div>
</div>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.absorption')}</h3>
<div className="flex-check-box for-line">
{settingsModalOptions.option2.map((item, index) => (
<button key={item.id || index} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
{settingsModalOptions &&
settingsModalOptions.option2.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
<span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span>
</button>
))}
</div>
<div className="flex-check-box for-line">
<button className="arr-btn">

View File

@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom'
import { fabric } from 'fabric'
@ -8,7 +8,7 @@ export function useEvent() {
const currentMenu = useRecoilValue(currentMenuState)
const keyboardEventListeners = useRef([])
const mouseEventListeners = useRef([])
const setCanvasZoom = useSetRecoilState(canvasZoomState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
useEffect(() => {
if (!canvas) {
@ -16,6 +16,13 @@ export function useEvent() {
}
removeAllMouseEventListeners()
removeAllDocumentEventListeners()
/**
* wheelEvent
*/
canvas?.off('mouse:wheel')
canvas?.on('mouse:wheel', wheelEvent)
addDefaultEvent()
}, [currentMenu, canvas])
@ -23,7 +30,7 @@ export function useEvent() {
//default Event 추가
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
addCanvasMouseEventListener('mouse:wheel', wheelEvent)
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
}
@ -126,10 +133,21 @@ export function useEvent() {
keyboardEventListeners.current.length = 0 // 배열 초기화
}
const removeMouseEvent = (type, handler) => {
mouseEventListeners.current = mouseEventListeners.current.filter((event) => {
if (event.type === type && event.handler === handler) {
canvas.off(type, handler)
return false
}
return true
})
}
return {
addDocumentEventListener,
addCanvasMouseEventListener,
removeAllMouseEventListeners,
removeAllDocumentEventListeners,
removeMouseEvent,
}
}

View File

@ -1280,13 +1280,44 @@ export function useMode() {
}
const templateSideMode = () => {
changeMode(canvas, Mode.EDIT)
if (historyPoints.current.length >= 4) {
const wall = drawWallPolygon()
setWall(wall)
const firstPoint = historyPoints.current[0]
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
historyPoints.current.forEach((point) => {
canvas?.remove(point)
})
drawLineWithLength(lastPoint, firstPoint)
console.log('sideWall', wall)
// 캔버스에서 모든 라인 객체를 찾습니다.
const lines = historyLines.current
historyLines.current = []
// 각 라인의 시작점과 끝점을 사용하여 다각형의 점 배열을 생성합니다.
const points = lines.map((line) => ({ x: line.x1, y: line.y1 }))
// 모든 라인 객체를 캔버스에서 제거합니다.
lines.forEach((line) => {
canvas?.remove(line)
})
// 점 배열을 사용하여 새로운 다각형 객체를 생성합니다.
const polygon = new QPolygon(
points,
{
stroke: 'black',
fill: 'transparent',
viewLengthText: true,
fontSize: 15,
selectable: true,
},
canvas,
)
// 새로운 다각형 객체를 캔버스에 추가합니다.
canvas.add(polygon)
changeMode(canvas, Mode.DEFAULT)
return polygon
}
}