Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
1430b187fa
@ -12,7 +12,7 @@ export default function QContextMenu(props) {
|
|||||||
let contextType = ''
|
let contextType = ''
|
||||||
|
|
||||||
if (activeObject) {
|
if (activeObject) {
|
||||||
if (activeObject.initOptions) {
|
if (activeObject.initOptions && activeObject.initOptions.name) {
|
||||||
//이건 바뀔 가능성이 있음
|
//이건 바뀔 가능성이 있음
|
||||||
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
|
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
|
||||||
contextType = 'surface' //면형상
|
contextType = 'surface' //면형상
|
||||||
|
|||||||
@ -4,20 +4,34 @@ import { useEffect, useState } from 'react'
|
|||||||
import MenuDepth01 from './MenuDepth01'
|
import MenuDepth01 from './MenuDepth01'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { post } from '@/lib/Axios'
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
|
||||||
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
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) {
|
export default function CanvasMenu(props) {
|
||||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
|
const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
|
||||||
const [menuNumber, setMenuNumber] = useState(null)
|
const [menuNumber, setMenuNumber] = useState(null)
|
||||||
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
||||||
const [vertical, setVertical] = useState(true)
|
|
||||||
const [type, setType] = useState('')
|
const [type, setType] = useState('')
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canvasZoom = useRecoilValue(canvasZoomState)
|
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 SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
||||||
const onClickNav = (number) => {
|
const onClickNav = (number) => {
|
||||||
setMenuNumber(number)
|
setMenuNumber(number)
|
||||||
@ -33,7 +47,13 @@ export default function CanvasMenu(props) {
|
|||||||
const firstOptions = useRecoilState(settingModalFirstOptionsState)
|
const firstOptions = useRecoilState(settingModalFirstOptionsState)
|
||||||
const secondOptions = useRecoilState(settingModalSecondOptionsState)
|
const secondOptions = useRecoilState(settingModalSecondOptionsState)
|
||||||
|
|
||||||
useEffect(() => {}, [menuNumber, type])
|
useEffect(() => {
|
||||||
|
if (globalLocale === 'ko') {
|
||||||
|
setAppMessageState(KO)
|
||||||
|
} else {
|
||||||
|
setAppMessageState(JA)
|
||||||
|
}
|
||||||
|
}, [menuNumber, type, globalLocale])
|
||||||
|
|
||||||
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
||||||
const handleSaveSettings = async () => {
|
const handleSaveSettings = async () => {
|
||||||
@ -60,6 +80,7 @@ export default function CanvasMenu(props) {
|
|||||||
|
|
||||||
const patternData = {
|
const patternData = {
|
||||||
objectNo,
|
objectNo,
|
||||||
|
//디스플레이 설정(다중)
|
||||||
assignDisplay: dataToSend.firstOption1[0].selected,
|
assignDisplay: dataToSend.firstOption1[0].selected,
|
||||||
drawDisplay: dataToSend.firstOption1[1].selected,
|
drawDisplay: dataToSend.firstOption1[1].selected,
|
||||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
gridDisplay: dataToSend.firstOption1[2].selected,
|
||||||
@ -71,9 +92,11 @@ export default function CanvasMenu(props) {
|
|||||||
trestleDisplay: dataToSend.firstOption1[8].selected,
|
trestleDisplay: dataToSend.firstOption1[8].selected,
|
||||||
coordiDisplay: dataToSend.firstOption1[9].selected,
|
coordiDisplay: dataToSend.firstOption1[9].selected,
|
||||||
drawConverDisplay: dataToSend.firstOption1[10].selected,
|
drawConverDisplay: dataToSend.firstOption1[10].selected,
|
||||||
|
//화면 표시(다중)
|
||||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
onlyBorder: dataToSend.firstOption2[0].selected,
|
||||||
lineHatch: dataToSend.firstOption2[1].selected,
|
lineHatch: dataToSend.firstOption2[1].selected,
|
||||||
allPainted: dataToSend.firstOption2[2].selected,
|
allPainted: dataToSend.firstOption2[2].selected,
|
||||||
|
//흡착범위 설정(단건)
|
||||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
||||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
||||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
||||||
@ -81,16 +104,19 @@ export default function CanvasMenu(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTTP POST 요청 보내기
|
// HTTP POST 요청 보내기
|
||||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
|
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
|
||||||
|
toastUp({ message: res.returnMessage, type: 'success' })
|
||||||
// 응답 처리
|
})
|
||||||
alert('설정이 저장되었습니다.')
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('설정을 저장하는 동안 오류가 발생했습니다:', error)
|
toastUp({ message: res.returnMessage, type: 'error' })
|
||||||
alert('설정을 저장하는 중 오류가 발생했습니다.')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setPoints([])
|
||||||
|
canvas?.clear()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
<div className="canvas-menu-inner">
|
<div className="canvas-menu-inner">
|
||||||
@ -111,6 +137,7 @@ export default function CanvasMenu(props) {
|
|||||||
className={`canvas-menu-item ${menuNumber === 2 ? 'active' : ''}`}
|
className={`canvas-menu-item ${menuNumber === 2 ? 'active' : ''}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClickNav(2)
|
onClickNav(2)
|
||||||
|
setCurrentMenu(MENU.ROOF_COVERING.DEFAULT)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button>
|
<button>
|
||||||
@ -118,25 +145,49 @@ export default function CanvasMenu(props) {
|
|||||||
{getMessage('plan.menu.roof.cover')}
|
{getMessage('plan.menu.roof.cover')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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>
|
<button>
|
||||||
<span className="menu-icon con03"></span>
|
<span className="menu-icon con03"></span>
|
||||||
{getMessage('plan.menu.placement.surface')}
|
{getMessage('plan.menu.placement.surface')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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>
|
<button>
|
||||||
<span className="menu-icon con04"></span>
|
<span className="menu-icon con04"></span>
|
||||||
{getMessage('plan.menu.module.circuit.setting')}
|
{getMessage('plan.menu.module.circuit.setting')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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>
|
<button>
|
||||||
<span className="menu-icon con06"></span>
|
<span className="menu-icon con06"></span>
|
||||||
{getMessage('plan.menu.estimate')}
|
{getMessage('plan.menu.estimate')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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>
|
<button>
|
||||||
<span className="menu-icon con05"></span>
|
<span className="menu-icon con05"></span>
|
||||||
{getMessage('plan.menu.simulation')}
|
{getMessage('plan.menu.simulation')}
|
||||||
@ -171,7 +222,7 @@ export default function CanvasMenu(props) {
|
|||||||
<button className="control-btn plus"></button>
|
<button className="control-btn plus"></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className="btn07"></button>
|
<button className="btn07" onClick={handleClear}></button>
|
||||||
<button className="btn08" onClick={handleSaveSettings}></button>
|
<button className="btn08" onClick={handleSaveSettings}></button>
|
||||||
<button className="btn09"></button>
|
<button className="btn09"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,14 +3,19 @@
|
|||||||
import { ToggleonMouse } from '@/components/header/Header'
|
import { ToggleonMouse } from '@/components/header/Header'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
|
import { useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
export default function MenuDepth01(props) {
|
export default function MenuDepth01(props) {
|
||||||
const { setShowOutlineModal, type } = props
|
const { setShowOutlineModal, type } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [activeMenu, setActiveMenu] = useState()
|
const [activeMenu, setActiveMenu] = useState()
|
||||||
const onClickMenu = (menuNum) => {
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
setActiveMenu(menuNum)
|
const onClickMenu = ({ id, menu, name }) => {
|
||||||
setShowOutlineModal(menuNum === 0)
|
setActiveMenu(menu)
|
||||||
|
setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||||
|
setCurrentMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
const menus = [
|
const menus = [
|
||||||
@ -26,21 +31,21 @@ export default function MenuDepth01(props) {
|
|||||||
const menuInfo = {
|
const menuInfo = {
|
||||||
outline: [
|
outline: [
|
||||||
// 지붕덮개
|
// 지붕덮개
|
||||||
{ id: 0, name: 'plan.menu.roof.cover.outline.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' },
|
{ 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' },
|
{ 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' },
|
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
||||||
],
|
],
|
||||||
surface: [
|
surface: [
|
||||||
// 배치면
|
// 배치면
|
||||||
{ id: 0, name: 'plan.menu.placement.surface.drawing' },
|
{ id: 0, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
|
||||||
{ id: 1, name: 'plan.menu.placement.surface.surface' },
|
{ id: 1, name: 'plan.menu.placement.surface.surface', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
|
||||||
{ id: 2, name: 'plan.menu.placement.surface.object' },
|
{ id: 2, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
|
||||||
],
|
],
|
||||||
module: [
|
module: [
|
||||||
// 모듈, 회로 구성
|
// 모듈, 회로 구성
|
||||||
{ id: 0, name: 'plan.menu.module.circuit.setting.default' },
|
{ 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' },
|
{ 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">
|
<ul className="canvas-depth2-list">
|
||||||
{menuInfo[type].map((menu) => {
|
{menuInfo[type].map((menu) => {
|
||||||
return (
|
return (
|
||||||
<li key={menu.id} className={`canvas-depth2-item ${menu.id === activeMenu ? 'active' : ''}`}>
|
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}>
|
||||||
<button onClick={() => onClickMenu(menu.id)}>{getMessage(menu.name)}</button>
|
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { useEvent } from '@/hooks/useEvent'
|
|||||||
import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
||||||
import {
|
import {
|
||||||
OUTER_LINE_TYPE,
|
OUTER_LINE_TYPE,
|
||||||
|
outerLineAngle1State,
|
||||||
outerLineArrow1State,
|
outerLineArrow1State,
|
||||||
outerLineArrow2State,
|
outerLineArrow2State,
|
||||||
outerLineLength1State,
|
outerLineLength1State,
|
||||||
@ -18,16 +19,19 @@ import {
|
|||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { distanceBetweenPoints } from '@/util/canvas-util'
|
import { distanceBetweenPoints } from '@/util/canvas-util'
|
||||||
|
import { calculateAngle } from '@/util/qpolygon-utils'
|
||||||
|
|
||||||
export default function OuterLineWall(props) {
|
export default function OuterLineWall(props) {
|
||||||
const { setShowOutlineModal } = props
|
const { setShowOutlineModal } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent()
|
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
|
||||||
|
useEvent()
|
||||||
const { addLineText, removeLineText } = useLine()
|
const { addLineText, removeLineText } = useLine()
|
||||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||||
|
|
||||||
const length1Ref = useRef(null)
|
const length1Ref = useRef(null)
|
||||||
const length2Ref = useRef(null)
|
const length2Ref = useRef(null)
|
||||||
|
const angle1Ref = useRef(null)
|
||||||
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
||||||
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
||||||
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
||||||
@ -37,11 +41,16 @@ export default function OuterLineWall(props) {
|
|||||||
const arrow1Ref = useRef(arrow1)
|
const arrow1Ref = useRef(arrow1)
|
||||||
const arrow2Ref = useRef(arrow2)
|
const arrow2Ref = useRef(arrow2)
|
||||||
|
|
||||||
|
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
|
||||||
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
removeAllMouseEventListeners()
|
removeMouseEvent('mouse:down', mouseDown)
|
||||||
addCanvasMouseEventListener('mouse:down', mouseDown)
|
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||||
|
return () => {
|
||||||
|
removeAllMouseEventListeners()
|
||||||
|
}
|
||||||
}, [verticalHorizontalMode, points])
|
}, [verticalHorizontalMode, points])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -164,6 +173,24 @@ export default function OuterLineWall(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
|
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], {
|
const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
|
||||||
stroke: 'grey',
|
stroke: 'grey',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@ -423,7 +450,25 @@ export default function OuterLineWall(props) {
|
|||||||
console.log('leegubae')
|
console.log('leegubae')
|
||||||
},
|
},
|
||||||
angle: (e) => {
|
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) => {
|
diagonalLine: (e) => {
|
||||||
console.log('diagonalLine')
|
console.log('diagonalLine')
|
||||||
@ -442,6 +487,27 @@ export default function OuterLineWall(props) {
|
|||||||
if (points.length < 3) {
|
if (points.length < 3) {
|
||||||
return
|
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) => {
|
setPoints((prev) => {
|
||||||
if (prev.length === 0) {
|
if (prev.length === 0) {
|
||||||
return []
|
return []
|
||||||
@ -449,6 +515,7 @@ export default function OuterLineWall(props) {
|
|||||||
return [...prev, { x: prev[0].x, y: prev[0].y }]
|
return [...prev, { x: prev[0].x, y: prev[0].y }]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: -1000 + 50 }}>
|
<WithDraggable isShow={true} pos={{ x: 50, y: -1000 + 50 }}>
|
||||||
<div className={`modal-pop-wrap ssm`}>
|
<div className={`modal-pop-wrap ssm`}>
|
||||||
@ -501,7 +568,8 @@ export default function OuterLineWall(props) {
|
|||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
onChange={(e) => {
|
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"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -521,7 +589,8 @@ export default function OuterLineWall(props) {
|
|||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
onChange={(e) => {
|
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"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -538,7 +607,8 @@ export default function OuterLineWall(props) {
|
|||||||
value={length2}
|
value={length2}
|
||||||
ref={length2Ref}
|
ref={length2Ref}
|
||||||
onChange={(e) => {
|
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"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -548,6 +618,44 @@ export default function OuterLineWall(props) {
|
|||||||
<input type="text" readOnly={true} value={arrow2} className="input-origin block" />
|
<input type="text" readOnly={true} value={arrow2} className="input-origin block" />
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,28 +1,24 @@
|
|||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import { get } from '@/lib/Axios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
|
|
||||||
export default function FirstOption() {
|
export default function FirstOption() {
|
||||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
|
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||||
const { option1, option2 } = settingsModalOptions
|
const { option1, option2 } = settingsModalOptions
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { get } = useAxios()
|
||||||
const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
|
|
||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('FirstOption useEffect 실행')
|
console.log('FirstOption useEffect 실행')
|
||||||
if (!isFetched) {
|
fetchSettings()
|
||||||
// 조회가 안 되었을 때만 fetchSettings 실행
|
}, [objectNo])
|
||||||
fetchSettings()
|
|
||||||
}
|
|
||||||
}, [isFetched]) // isFetched 상태가 변할 때마다 확인
|
|
||||||
|
|
||||||
// Canvas Setting 조회 및 초기화
|
// Canvas Setting 조회 및 초기화
|
||||||
const fetchSettings = async () => {
|
const fetchSettings = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
||||||
|
|
||||||
@ -49,12 +45,10 @@ export default function FirstOption() {
|
|||||||
option1,
|
option1,
|
||||||
option2,
|
option2,
|
||||||
})
|
})
|
||||||
|
|
||||||
setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Data fetching error:', error)
|
console.error('Data fetching error:', error)
|
||||||
}
|
}
|
||||||
}
|
}, [objectNo])
|
||||||
|
|
||||||
const onClickOption = (option) => {
|
const onClickOption = (option) => {
|
||||||
option.selected = !option.selected
|
option.selected = !option.selected
|
||||||
@ -67,23 +61,25 @@ export default function FirstOption() {
|
|||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
<h3 className="check-wrap-title light">{getMessage('modal.canvas.setting.first.option.info')}</h3>
|
<h3 className="check-wrap-title light">{getMessage('modal.canvas.setting.first.option.info')}</h3>
|
||||||
<div className="flex-check-box for2">
|
<div className="flex-check-box for2">
|
||||||
{settingsModalOptions?.option1?.map((item) => (
|
{settingsModalOptions &&
|
||||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
settingsModalOptions.option1.map((item) => (
|
||||||
<span className="check-area"></span>
|
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||||
<span className="title-area">{getMessage(item.name)}</span>
|
<span className="check-area"></span>
|
||||||
</button>
|
<span className="title-area">{getMessage(item.name)}</span>
|
||||||
))}
|
</button>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.first.option.display')}</h3>
|
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.first.option.display')}</h3>
|
||||||
<div className="flex-check-box for-line">
|
<div className="flex-check-box for-line">
|
||||||
{settingsModalOptions?.option2?.map((item) => (
|
{settingsModalOptions &&
|
||||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
settingsModalOptions.option2.map((item) => (
|
||||||
<span className="check-area"></span>
|
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||||
<span className="title-area">{getMessage(item.name)}</span>
|
<span className="check-area"></span>
|
||||||
</button>
|
<span className="title-area">{getMessage(item.name)}</span>
|
||||||
))}
|
</button>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -1,27 +1,24 @@
|
|||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { settingModalSecondOptionsState } from '@/store/settingAtom'
|
import { settingModalSecondOptionsState } from '@/store/settingAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import { get } from '@/lib/Axios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
|
|
||||||
export default function SecondOption() {
|
export default function SecondOption() {
|
||||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
|
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
|
||||||
const { option1, option2 } = settingsModalOptions
|
const { option1, option2 } = settingsModalOptions
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { get } = useAxios()
|
||||||
const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
|
|
||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('SecondOption useEffect 실행')
|
console.log('SecondOption useEffect 실행')
|
||||||
if (!isFetched) {
|
fetchSettings()
|
||||||
// 조회가 안 되었을 때만 fetchSettings 실행
|
}, [objectNo])
|
||||||
fetchSettings()
|
|
||||||
}
|
|
||||||
}, [isFetched]) // isFetched 상태가 변할 때마다 확인
|
|
||||||
|
|
||||||
const fetchSettings = async () => {
|
// Canvas Setting 조회 및 초기화
|
||||||
|
const fetchSettings = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
||||||
|
|
||||||
@ -36,12 +33,10 @@ export default function SecondOption() {
|
|||||||
option1,
|
option1,
|
||||||
option2,
|
option2,
|
||||||
})
|
})
|
||||||
|
|
||||||
setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Data fetching error:', error)
|
console.error('Data fetching error:', error)
|
||||||
}
|
}
|
||||||
}
|
}, [objectNo])
|
||||||
|
|
||||||
const onClickOption = (option) => {
|
const onClickOption = (option) => {
|
||||||
// option2에서 한 개만 선택 가능하도록 처리
|
// option2에서 한 개만 선택 가능하도록 처리
|
||||||
@ -54,22 +49,24 @@ export default function SecondOption() {
|
|||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.edit')}</h3>
|
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.edit')}</h3>
|
||||||
<div className="flex-check-box for2">
|
<div className="flex-check-box for2">
|
||||||
{settingsModalOptions.option1.map((item, index) => (
|
{settingsModalOptions &&
|
||||||
<button key={item.id || index} className="arr-btn">
|
settingsModalOptions.option1.map((item) => (
|
||||||
<span>{getMessage(item.name)}</span>
|
<button key={item.id} className="arr-btn">
|
||||||
</button>
|
<span>{getMessage(item.name)}</span>
|
||||||
))}
|
</button>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.absorption')}</h3>
|
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.absorption')}</h3>
|
||||||
<div className="flex-check-box for-line">
|
<div className="flex-check-box for-line">
|
||||||
{settingsModalOptions.option2.map((item, index) => (
|
{settingsModalOptions &&
|
||||||
<button key={item.id || index} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
|
settingsModalOptions.option2.map((item) => (
|
||||||
<span className="check-area"></span>
|
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
|
||||||
<span className="title-area">{getMessage(item.name)}</span>
|
<span className="check-area"></span>
|
||||||
</button>
|
<span className="title-area">{getMessage(item.name)}</span>
|
||||||
))}
|
</button>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-check-box for-line">
|
<div className="flex-check-box for-line">
|
||||||
<button className="arr-btn">
|
<button className="arr-btn">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom'
|
import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ export function useEvent() {
|
|||||||
const currentMenu = useRecoilValue(currentMenuState)
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
const keyboardEventListeners = useRef([])
|
const keyboardEventListeners = useRef([])
|
||||||
const mouseEventListeners = useRef([])
|
const mouseEventListeners = useRef([])
|
||||||
const setCanvasZoom = useSetRecoilState(canvasZoomState)
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -16,6 +16,13 @@ export function useEvent() {
|
|||||||
}
|
}
|
||||||
removeAllMouseEventListeners()
|
removeAllMouseEventListeners()
|
||||||
removeAllDocumentEventListeners()
|
removeAllDocumentEventListeners()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wheelEvent
|
||||||
|
*/
|
||||||
|
canvas?.off('mouse:wheel')
|
||||||
|
canvas?.on('mouse:wheel', wheelEvent)
|
||||||
|
|
||||||
addDefaultEvent()
|
addDefaultEvent()
|
||||||
}, [currentMenu, canvas])
|
}, [currentMenu, canvas])
|
||||||
|
|
||||||
@ -23,7 +30,7 @@ export function useEvent() {
|
|||||||
//default Event 추가
|
//default Event 추가
|
||||||
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
||||||
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
|
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
|
||||||
addCanvasMouseEventListener('mouse:wheel', wheelEvent)
|
|
||||||
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
|
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,10 +133,21 @@ export function useEvent() {
|
|||||||
keyboardEventListeners.current.length = 0 // 배열 초기화
|
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 {
|
return {
|
||||||
addDocumentEventListener,
|
addDocumentEventListener,
|
||||||
addCanvasMouseEventListener,
|
addCanvasMouseEventListener,
|
||||||
removeAllMouseEventListeners,
|
removeAllMouseEventListeners,
|
||||||
removeAllDocumentEventListeners,
|
removeAllDocumentEventListeners,
|
||||||
|
removeMouseEvent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1280,13 +1280,44 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const templateSideMode = () => {
|
const templateSideMode = () => {
|
||||||
changeMode(canvas, Mode.EDIT)
|
|
||||||
|
|
||||||
if (historyPoints.current.length >= 4) {
|
if (historyPoints.current.length >= 4) {
|
||||||
const wall = drawWallPolygon()
|
const firstPoint = historyPoints.current[0]
|
||||||
setWall(wall)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user