'use client' import { useCallback, useEffect, useRef } from 'react' import WithDraggable from '@/components/common/draggable/withDraggable' import { modalState } from '@/store/modalAtom' import { useRecoilState, useRecoilValue } from 'recoil' import { useMessage } from '@/hooks/useMessage' import { useEvent } from '@/hooks/useEvent' import { canvasState } from '@/store/canvasAtom' import { OUTER_LINE_TYPE, outerLineArrow1State, outerLineArrow2State, outerLineLength1State, outerLineLength2State, outerLinePointsState, outerLineTypeState, } from '@/store/outerLineAtom' import { QLine } from '@/components/fabric/QLine' import { useLine } from '@/hooks/useLine' export default function OuterLineWall() { const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state const { getMessage } = useMessage() const { addCanvasMouseEventListener, addDocumentEventListener, removeAllDocumentEventListeners } = useEvent() const { addLineText, removeLineText } = useLine() const length1Ref = useRef(null) const length2Ref = useRef(null) const [length1, setLength1] = useRecoilState(outerLineLength1State) const [length2, setLength2] = useRecoilState(outerLineLength2State) const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State) const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State) const [points, setPoints] = useRecoilState(outerLinePointsState) const [type, setType] = useRecoilState(outerLineTypeState) const arrow1Ref = useRef(arrow1) const arrow2Ref = useRef(arrow2) const canvas = useRecoilValue(canvasState) useEffect(() => { addCanvasMouseEventListener('mouse:down', mouseDown) }, []) useEffect(() => { arrow1Ref.current = arrow1 }, [arrow1]) useEffect(() => { arrow2Ref.current = arrow2 }, [arrow2]) useEffect(() => { removeAllDocumentEventListeners() addDocumentEventListener('keydown', document, keydown[type]) clear() }, [type]) const clear = () => { setLength1(0) setLength2(0) setArrow1('') setArrow2('') } const mouseDown = (e) => { const pointer = canvas.getPointer(e.e) setPoints((prev) => [...prev, pointer]) } useEffect(() => { canvas ?.getObjects() .filter((obj) => obj.name === 'outerLine') .forEach((obj) => { canvas?.remove(obj) removeLineText(obj) }) canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) if (points.length === 0) { return } if (points.length === 1) { const point = new fabric.Circle({ radius: 5, fill: 'transparent', stroke: 'red', left: points[0].x - 5, top: points[0].y - 5, selectable: false, name: 'startPoint', }) canvas?.add(point) } else { points.forEach((point, idx) => { if (idx === 0) { return } drawLine(points[idx - 1], point, idx) }) } }, [points]) const drawLine = (point1, point2, idx) => { const line = new QLine([point1.x, point1.y, point2.x, point2.y], { stroke: 'black', strokeWidth: 1, idx: idx, selectable: false, name: 'outerLine', }) canvas?.add(line) addLineText(line) } // 직각 완료될 경우 확인 const checkRightAngle = () => { const length1Num = Number(length1Ref.current.value) / 10 const length2Num = Number(length2Ref.current.value) / 10 if (points.length === 0) { return } if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') { return } if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y + length1Num }] }) } else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y + length1Num }] }) } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y - length1Num }] }) } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y - length1Num }] }) } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y + length2Num }] }) } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y - length2Num }] }) } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y + length2Num }] }) } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y - length2Num }] }) } } const keydown = { outerLine: (e) => { const key = e.key if (!length1Ref.current) { return } const lengthNum = Number(length1Ref.current.value) / 10 if (lengthNum === 0) { return } switch (key) { case 'Down': // IE/Edge에서 사용되는 값 case 'ArrowDown': { setArrow1('↓') setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y + lengthNum }] }) break } case 'Up': // IE/Edge에서 사용되는 값 case 'ArrowUp': setArrow1('↑') setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y - lengthNum }] }) break case 'Left': // IE/Edge에서 사용되는 값 case 'ArrowLeft': setArrow1('←') setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x - lengthNum, y: prev[prev.length - 1].y }] }) break case 'Right': // IE/Edge에서 사용되는 값 case 'ArrowRight': setArrow1('→') setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[prev.length - 1].x + lengthNum, y: prev[prev.length - 1].y }] }) break } }, rightAngle: (e) => { const key = e.key const activeElem = document.activeElement const length1Num = Number(length1Ref.current.value) / 10 const length2Num = Number(length2Ref.current.value) / 10 switch (key) { case 'Down': // IE/Edge에서 사용되는 값 case 'ArrowDown': { if (activeElem === length1Ref.current) { setArrow1('↓') arrow1Ref.current = '↓' length2Ref.current.focus() } else if (activeElem === length2Ref.current) { if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') { break } setArrow2('↓') arrow2Ref.current = '↓' checkRightAngle() } break } case 'Up': // IE/Edge에서 사용되는 값 case 'ArrowUp': if (activeElem === length1Ref.current) { setArrow1('↑') arrow1Ref.current = '↑' length2Ref.current.focus() } else if (activeElem === length2Ref.current) { if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') { break } setArrow2('↑') arrow2Ref.current = '↑' checkRightAngle() } break case 'Left': // IE/Edge에서 사용되는 값 case 'ArrowLeft': if (activeElem === length1Ref.current) { setArrow1('←') arrow1Ref.current = '←' length2Ref.current.focus() } else if (activeElem === length2Ref.current) { if (arrow1Ref.current === '←' || arrow1Ref.current === '→') { break } setArrow2('←') arrow2Ref.current = '←' checkRightAngle() } break case 'Right': // IE/Edge에서 사용되는 값 case 'ArrowRight': if (activeElem === length1Ref.current) { setArrow1('→') arrow1Ref.current = '→' length2Ref.current.focus() } else if (activeElem === length2Ref.current) { if (arrow1Ref.current === '←' || arrow1Ref.current === '→') { break } setArrow2('→') arrow2Ref.current = '→' checkRightAngle() } break } }, leeGubae: (e) => { console.log('leegubae') }, angle: (e) => { console.log('angle') }, diagonalLine: (e) => { console.log('diagonalLine') }, } /** * 일변전으로 돌아가기 */ const handleRollback = () => { //points의 마지막 요소를 제거 setPoints((prev) => prev.slice(0, prev.length - 1)) } const handleClickClose = () => { setModalOption({ ...modalOption, outerwall: false }) } const handleFix = () => { setPoints((prev) => { if (prev.length === 0) { return [] } return [...prev, { x: prev[0].x, y: prev[0].y }] }) } return (

{getMessage('modal.cover.outline.drawing')}

{getMessage('modal.cover.outline.setting')}

{type === OUTER_LINE_TYPE.OUTER_LINE ? (
{ setLength1(e.target.value.replace(/[^-0-9]/g, '')) }} placeholder="3000" />
) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
{ setLength1(e.target.value.replace(/[^-0-9]/g, '')) }} placeholder="3000" />
{ setLength2(e.target.value.replace(/[^-0-9]/g, '')) }} placeholder="3000" />
) : ( <> )}
) }