보조선 작성 추가
This commit is contained in:
parent
d4e2952024
commit
0825196cea
@ -17,7 +17,7 @@ import GridColorSetting from './modal/grid/GridColorSetting'
|
||||
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
|
||||
import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing'
|
||||
import Slope from '@/components/floor-plan/modal/Slope'
|
||||
import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting'
|
||||
|
||||
import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing'
|
||||
|
||||
export default function FloorPlan() {
|
||||
@ -122,9 +122,6 @@ export default function FloorPlan() {
|
||||
{showPropertiesSettingModal && <PropertiesSetting {...propertiesSettingProps} />}
|
||||
{showPlaceShapeModal && <PlacementShapeSetting setShowPlaceShapeModal={setShowPlaceShapeModal} />}
|
||||
{showRoofShapeSettingModal && <RoofShapeSetting setShowRoofShapeSettingModal={setShowRoofShapeSettingModal} />}
|
||||
{showRoofShapePassivitySettingModal && (
|
||||
<RoofShapePassivitySetting setShowRoofShapePassivitySettingModal={setShowRoofShapePassivitySettingModal} />
|
||||
)}
|
||||
{showAuxiliaryModal && <AuxiliaryDrawing setShowAuxiliaryModal={setShowAuxiliaryModal} />}
|
||||
{showSlopeSettingModal && <Slope setShowSlopeSettingModal={setShowSlopeSettingModal} />}
|
||||
{showPlaceShapeDrawingModal && <PlacementShapeDrawing setShowPlaceShapeDrawingModal={setShowPlaceShapeDrawingModal} />}
|
||||
|
||||
@ -8,10 +8,11 @@ import Diagonal from '@/components/floor-plan/modal/lineTypes/Diagonal'
|
||||
import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
|
||||
import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall'
|
||||
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
|
||||
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
||||
|
||||
export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
||||
const { getMessage } = useMessage()
|
||||
const [buttonAct, setButtonAct] = useState(1)
|
||||
|
||||
const types = [
|
||||
{ id: 1, name: getMessage('straight.line'), type: OUTER_LINE_TYPE.OUTER_LINE },
|
||||
{ id: 2, name: getMessage('right.angle'), type: OUTER_LINE_TYPE.RIGHT_ANGLE },
|
||||
@ -19,6 +20,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
||||
{ id: 4, name: getMessage('angle'), type: OUTER_LINE_TYPE.ANGLE },
|
||||
{ id: 5, name: getMessage('diagonal'), type: OUTER_LINE_TYPE.DIAGONAL_LINE },
|
||||
]
|
||||
|
||||
const {
|
||||
length1,
|
||||
setLength1,
|
||||
@ -45,7 +47,9 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
||||
outerLineDiagonalLengthRef,
|
||||
handleRollback,
|
||||
handleFix,
|
||||
} = useOuterLineWall()
|
||||
buttonAct,
|
||||
setButtonAct,
|
||||
} = useAuxiliaryDrawing()
|
||||
|
||||
const outerLineProps = {
|
||||
length1,
|
||||
@ -129,8 +133,8 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="modal-btn-wrap">
|
||||
{types.map((type) => (
|
||||
<button className={`btn-frame modal ${buttonAct === type.id ? 'act' : ''}`} onClick={() => onClickButton(type)}>
|
||||
{types.map((type, idx) => (
|
||||
<button key={idx} className={`btn-frame modal ${buttonAct === type.id ? 'act' : ''}`} onClick={() => onClickButton(type)}>
|
||||
{type.name}
|
||||
</button>
|
||||
))}
|
||||
@ -144,8 +148,12 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
|
||||
{buttonAct === 5 && <Diagonal props={diagonalLineProps} />}
|
||||
</div>
|
||||
<div className="grid-btn-wrap">
|
||||
<button className="btn-frame modal mr5">{getMessage('modal.cover.outline.rollback')}</button>
|
||||
<button className="btn-frame modal act">{getMessage('modal.cover.outline.fix')}</button>
|
||||
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
||||
{getMessage('modal.cover.outline.rollback')}
|
||||
</button>
|
||||
<button className="btn-frame modal act" onClick={() => handleFix(setShowAuxiliaryModal)}>
|
||||
{getMessage('modal.cover.outline.fix')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
663
src/hooks/roofcover/useAuxiliaryDrawing.js
Normal file
663
src/hooks/roofcover/useAuxiliaryDrawing.js
Normal file
@ -0,0 +1,663 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import {
|
||||
adsorptionPointAddModeState,
|
||||
adsorptionPointModeState,
|
||||
adsorptionRangeState,
|
||||
canvasState,
|
||||
dotLineIntervalSelector,
|
||||
verticalHorizontalModeState,
|
||||
} from '@/store/canvasAtom'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { useMouse } from '@/hooks/useMouse'
|
||||
import { useLine } from '@/hooks/useLine'
|
||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||
import {
|
||||
OUTER_LINE_TYPE,
|
||||
outerLineAngle1State,
|
||||
outerLineAngle2State,
|
||||
outerLineArrow1State,
|
||||
outerLineArrow2State,
|
||||
outerLineDiagonalState,
|
||||
outerLineLength1State,
|
||||
outerLineLength2State,
|
||||
outerLineTypeState,
|
||||
} from '@/store/outerLineAtom'
|
||||
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
|
||||
import { fabric } from 'fabric'
|
||||
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||
|
||||
export function useAuxiliaryDrawing() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const {
|
||||
addCanvasMouseEventListener,
|
||||
addDocumentEventListener,
|
||||
removeAllMouseEventListeners,
|
||||
removeAllDocumentEventListeners,
|
||||
removeMouseEvent,
|
||||
removeMouseLine,
|
||||
initEvent,
|
||||
} = useEvent()
|
||||
const { getIntersectMousePoint } = useMouse()
|
||||
const { addLine, removeLine } = useLine()
|
||||
const { tempGridMode } = useTempGrid()
|
||||
const { getAdsorptionPoints } = useAdsorptionPoint()
|
||||
|
||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
||||
const adsorptionPointMode = useRecoilValue(adsorptionPointModeState)
|
||||
const adsorptionRange = useRecoilValue(adsorptionRangeState)
|
||||
const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격
|
||||
|
||||
const [buttonAct, setButtonAct] = useState(1)
|
||||
|
||||
const mousePointerArr = useRef([])
|
||||
const roofAdsorptionPoints = useRef([])
|
||||
const lineHistory = useRef([])
|
||||
|
||||
const length1Ref = useRef(0)
|
||||
const length2Ref = useRef(0)
|
||||
const angle1Ref = useRef('')
|
||||
const angle2Ref = useRef('')
|
||||
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
||||
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
||||
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
||||
const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
|
||||
const [type, setType] = useRecoilState(outerLineTypeState)
|
||||
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
|
||||
const [angle2, setAngle2] = useRecoilState(outerLineAngle2State)
|
||||
const [outerLineDiagonalLength, setOuterLineDiagonalLength] = useRecoilState(outerLineDiagonalState)
|
||||
const arrow1Ref = useRef(arrow1)
|
||||
const arrow2Ref = useRef(arrow2)
|
||||
|
||||
const typeRef = useRef(type)
|
||||
|
||||
const outerLineDiagonalLengthRef = useRef(0)
|
||||
const intersectionPoints = useRef([])
|
||||
|
||||
useEffect(() => {
|
||||
arrow1Ref.current = arrow1
|
||||
}, [arrow1])
|
||||
|
||||
useEffect(() => {
|
||||
arrow2Ref.current = arrow2
|
||||
}, [arrow2])
|
||||
|
||||
useEffect(() => {
|
||||
typeRef.current = type
|
||||
}, [type])
|
||||
|
||||
useEffect(() => {
|
||||
// innerLines가 있을경우 삭제
|
||||
const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roofBase')
|
||||
if (roofs.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// 지붕의 각 꼭지점을 흡착점으로 설정
|
||||
const roofsPoints = roofs.map((roof) => roof.points).flat()
|
||||
roofAdsorptionPoints.current = [...roofsPoints]
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', mouseMove)
|
||||
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||
addDocumentEventListener('contextmenu', document, cutAuxiliary)
|
||||
addDocumentEventListener('keydown', document, keydown)
|
||||
|
||||
return () => {
|
||||
canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'innerPoint'))
|
||||
initEvent()
|
||||
canvas.renderAll()
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
clear()
|
||||
addDocumentEventListener('keydown', document, keydown[type])
|
||||
}, [type])
|
||||
|
||||
const clear = () => {
|
||||
setLength1(0)
|
||||
setLength2(0)
|
||||
|
||||
setArrow1('')
|
||||
setArrow2('')
|
||||
|
||||
setAngle1(0)
|
||||
setAngle2(0)
|
||||
|
||||
setOuterLineDiagonalLength(0)
|
||||
}
|
||||
|
||||
const keydown = {
|
||||
outerLine: (e) => {
|
||||
console.log(123)
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
// 포커스가 length1에 있지 않으면 length1에 포커스를 줌
|
||||
const activeElem = document.activeElement
|
||||
if (activeElem !== length1Ref.current) {
|
||||
length1Ref.current.focus()
|
||||
}
|
||||
|
||||
const key = e.key
|
||||
|
||||
if (!length1Ref.current) {
|
||||
return
|
||||
}
|
||||
|
||||
const lengthNum = Number(length1Ref.current.value) / 10
|
||||
if (lengthNum === 0) {
|
||||
return
|
||||
}
|
||||
const lastPoint = mousePointerArr.current[0]
|
||||
switch (key) {
|
||||
case 'Down': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowDown': {
|
||||
setArrow1('↓')
|
||||
mousePointerArr.current.push({ x: lastPoint.x, y: lastPoint.y + lengthNum })
|
||||
drawLine()
|
||||
break
|
||||
}
|
||||
case 'Up': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowUp':
|
||||
setArrow1('↑')
|
||||
mousePointerArr.current.push({ x: lastPoint.x, y: lastPoint.y - lengthNum })
|
||||
drawLine()
|
||||
break
|
||||
case 'Left': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowLeft':
|
||||
setArrow1('←')
|
||||
mousePointerArr.current.push({ x: lastPoint.x - lengthNum, y: lastPoint.y })
|
||||
drawLine()
|
||||
break
|
||||
case 'Right': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowRight':
|
||||
setArrow1('→')
|
||||
mousePointerArr.current.push({ x: lastPoint.x + lengthNum, y: lastPoint.y })
|
||||
drawLine()
|
||||
break
|
||||
}
|
||||
},
|
||||
rightAngle: (e) => {
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
const key = e.key
|
||||
|
||||
const activeElem = document.activeElement
|
||||
if (activeElem !== length1Ref.current && activeElem !== length2Ref.current) {
|
||||
length1Ref.current.focus()
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case 'Down': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowDown': {
|
||||
checkRightAngle('↓')
|
||||
break
|
||||
}
|
||||
case 'Up': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowUp':
|
||||
checkRightAngle('↑')
|
||||
break
|
||||
case 'Left': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowLeft':
|
||||
checkRightAngle('←')
|
||||
break
|
||||
case 'Right': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowRight':
|
||||
checkRightAngle('→')
|
||||
break
|
||||
}
|
||||
},
|
||||
doublePitch: (e) => {
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
const key = e.key
|
||||
switch (key) {
|
||||
case 'Down': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowDown': {
|
||||
checkDoublePitch('↓')
|
||||
break
|
||||
}
|
||||
case 'Up': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowUp':
|
||||
checkDoublePitch('↑')
|
||||
break
|
||||
case 'Left': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowLeft':
|
||||
checkDoublePitch('←')
|
||||
break
|
||||
case 'Right': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowRight':
|
||||
checkDoublePitch('→')
|
||||
break
|
||||
}
|
||||
},
|
||||
angle: (e) => {
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
const key = e.key
|
||||
switch (key) {
|
||||
case 'Enter': {
|
||||
const lastPoint = mousePointerArr.current[0]
|
||||
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) => {
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const key = e.key
|
||||
switch (key) {
|
||||
case 'Down': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowDown': {
|
||||
checkDiagonal('↓')
|
||||
break
|
||||
}
|
||||
case 'Up': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowUp':
|
||||
checkDiagonal('↑')
|
||||
break
|
||||
case 'Left': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowLeft':
|
||||
checkDiagonal('←')
|
||||
break
|
||||
case 'Right': // IE/Edge에서 사용되는 값
|
||||
case 'ArrowRight':
|
||||
checkDiagonal('→')
|
||||
break
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// 직각 완료될 경우 확인
|
||||
const checkRightAngle = (direction) => {
|
||||
const activeElem = document.activeElement
|
||||
|
||||
const canDirection =
|
||||
direction === '↓' || direction === '↑'
|
||||
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
|
||||
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
|
||||
|
||||
if (activeElem === length1Ref.current || activeElem === angle1Ref.current) {
|
||||
setArrow1(direction)
|
||||
arrow1Ref.current = direction
|
||||
length2Ref.current.focus()
|
||||
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
|
||||
if (!canDirection) {
|
||||
return
|
||||
}
|
||||
setArrow2(direction)
|
||||
arrow2Ref.current = direction
|
||||
}
|
||||
|
||||
const length1Num = Number(length1Ref.current.value) / 10
|
||||
const length2Num = Number(length2Ref.current.value) / 10
|
||||
|
||||
if (mousePointerArr.current.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const lastPoint = mousePointerArr.current[0]
|
||||
|
||||
if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') {
|
||||
return
|
||||
}
|
||||
|
||||
if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Num, y: lastPoint.y + length1Num })
|
||||
} else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Num, y: lastPoint.y + length1Num })
|
||||
} else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Num, y: lastPoint.y - length1Num })
|
||||
} else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Num, y: lastPoint.y - length1Num })
|
||||
} else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Num, y: lastPoint.y + length2Num })
|
||||
} else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Num, y: lastPoint.y - length2Num })
|
||||
} else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length1Num, y: lastPoint.y + length2Num })
|
||||
} else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length1Num, y: lastPoint.y - length2Num })
|
||||
}
|
||||
drawLine()
|
||||
}
|
||||
|
||||
//이구배 완료될 경우 확인 ↓, ↑, ←, →
|
||||
const checkDoublePitch = (direction) => {
|
||||
const activeElem = document.activeElement
|
||||
|
||||
const canDirection =
|
||||
direction === '↓' || direction === '↑'
|
||||
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
|
||||
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
|
||||
|
||||
if (activeElem === length1Ref.current || activeElem === angle1Ref.current) {
|
||||
setArrow1(direction)
|
||||
arrow1Ref.current = direction
|
||||
angle2Ref.current.focus()
|
||||
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
|
||||
if (!canDirection) {
|
||||
return
|
||||
}
|
||||
setArrow2(direction)
|
||||
arrow2Ref.current = direction
|
||||
}
|
||||
|
||||
const angle1Value = Number(angle1Ref.current.value)
|
||||
const angle2Value = Number(angle2Ref.current.value)
|
||||
const length1Value = Number(length1Ref.current.value)
|
||||
const length2Value = Number(length2Ref.current.value)
|
||||
|
||||
const arrow1Value = arrow1Ref.current
|
||||
const arrow2Value = arrow2Ref.current
|
||||
const lastPoint = mousePointerArr.current[0]
|
||||
|
||||
if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') {
|
||||
if (arrow1Value === '↓' && arrow2Value === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Value / 10, y: lastPoint.y + length2Value / 10 })
|
||||
} else if (arrow1Value === '↓' && arrow2Value === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length1Value / 10, y: lastPoint.y + length2Value / 10 })
|
||||
} else if (arrow1Value === '↑' && arrow2Value === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Value / 10, y: lastPoint.y - length2Value / 10 })
|
||||
} else if (arrow1Value === '↑' && arrow2Value === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length1Value / 10, y: lastPoint.y - length2Value / 10 })
|
||||
} else if (arrow1Value === '→' && arrow2Value === '↓') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Value / 10, y: lastPoint.y + length1Value / 10 })
|
||||
} else if (arrow1Value === '→' && arrow2Value === '↑') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Value / 10, y: lastPoint.y - length1Value / 10 })
|
||||
} else if (arrow1Value === '←' && arrow2Value === '↓') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Value / 10, y: lastPoint.y + length1Value / 10 })
|
||||
} else if (arrow1Value === '←' && arrow2Value === '↑') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Value / 10, y: lastPoint.y - length1Value / 10 })
|
||||
}
|
||||
drawLine()
|
||||
|
||||
angle1Ref.current.focus()
|
||||
}
|
||||
}
|
||||
|
||||
//대각선 완료될 경우 확인
|
||||
const checkDiagonal = (direction) => {
|
||||
const activeElem = document.activeElement
|
||||
const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이
|
||||
|
||||
const length1Value = length1Ref.current.value
|
||||
|
||||
if (diagonalLength <= length1Value) {
|
||||
alert('대각선 길이는 직선 길이보다 길어야 합니다.')
|
||||
return
|
||||
}
|
||||
|
||||
const canDirection =
|
||||
direction === '↓' || direction === '↑'
|
||||
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
|
||||
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
|
||||
|
||||
if (activeElem === length1Ref.current) {
|
||||
setArrow1(direction)
|
||||
arrow1Ref.current = direction
|
||||
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
|
||||
if (!canDirection) {
|
||||
return
|
||||
}
|
||||
setArrow2(direction)
|
||||
arrow2Ref.current = direction
|
||||
}
|
||||
|
||||
const arrow1Value = arrow1Ref.current
|
||||
const arrow2Value = arrow2Ref.current
|
||||
|
||||
const getLength2 = () => {
|
||||
return Math.floor(Math.sqrt(diagonalLength ** 2 - length1Value ** 2))
|
||||
}
|
||||
|
||||
const length2Value = getLength2()
|
||||
|
||||
if (diagonalLength !== 0 && length1Value !== 0 && arrow1Value !== '') {
|
||||
setLength2(getLength2())
|
||||
length2Ref.current.focus()
|
||||
}
|
||||
|
||||
const lastPoint = mousePointerArr.current[0]
|
||||
|
||||
if (length1Value !== 0 && length2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') {
|
||||
if (arrow1Value === '↓' && arrow2Value === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Value / 10, y: lastPoint.y + length1Value / 10 })
|
||||
} else if (arrow1Value === '↓' && arrow2Value === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Value / 10, y: lastPoint.y + length1Value / 10 })
|
||||
} else if (arrow1Value === '↑' && arrow2Value === '→') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length2Value / 10, y: lastPoint.y - length1Value / 10 })
|
||||
} else if (arrow1Value === '↑' && arrow2Value === '←') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x - length2Value / 10, y: lastPoint.y - length1Value / 10 })
|
||||
} else if (arrow1Value === '→' && arrow2Value === '↓') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Value / 10, y: lastPoint.y + length2Value / 10 })
|
||||
} else if (arrow1Value === '→' && arrow2Value === '↑') {
|
||||
mousePointerArr.current.push({ x: lastPoint.x + length1Value / 10, y: lastPoint.y - length2Value / 10 })
|
||||
}
|
||||
drawLine()
|
||||
}
|
||||
}
|
||||
|
||||
const drawLine = () => {
|
||||
canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'innerPoint'))
|
||||
const line = addLine([mousePointerArr.current[0].x, mousePointerArr.current[0].y, mousePointerArr.current[1].x, mousePointerArr.current[1].y], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
name: 'auxiliaryLine',
|
||||
})
|
||||
|
||||
lineHistory.current.push(line)
|
||||
mousePointerArr.current = []
|
||||
clear()
|
||||
}
|
||||
|
||||
const mouseDown = (e) => {
|
||||
const pointer = getIntersectMousePoint(e)
|
||||
|
||||
mousePointerArr.current.push(pointer)
|
||||
if (mousePointerArr.current.length === 2) {
|
||||
drawLine(mousePointerArr.current[0], mousePointerArr.current[1])
|
||||
} else {
|
||||
const circle = new fabric.Circle({
|
||||
radius: 3,
|
||||
fill: 'red',
|
||||
left: pointer.x - 3,
|
||||
top: pointer.y - 3,
|
||||
x: pointer.x,
|
||||
y: pointer.y,
|
||||
name: 'innerPoint',
|
||||
selectable: true,
|
||||
})
|
||||
canvas.add(circle)
|
||||
canvas.renderAll()
|
||||
}
|
||||
}
|
||||
|
||||
const mouseMove = (e) => {
|
||||
removeMouseLine()
|
||||
// 가로선
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed)
|
||||
|
||||
const otherAdsorptionPoints = []
|
||||
|
||||
auxiliaryLines.forEach((line1) => {
|
||||
auxiliaryLines.forEach((line2) => {
|
||||
const lines = [line1, line2]
|
||||
if (line1 === line2) {
|
||||
return
|
||||
}
|
||||
|
||||
const intersectionPoint = calculateIntersection(line1, line2)
|
||||
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
|
||||
return
|
||||
}
|
||||
otherAdsorptionPoints.push(intersectionPoint)
|
||||
})
|
||||
})
|
||||
|
||||
const adsorptionPoints = [...getAdsorptionPoints(), ...roofAdsorptionPoints.current, ...otherAdsorptionPoints, ...intersectionPoints.current]
|
||||
|
||||
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
||||
|
||||
// pointer와 adsorptionPoints의 거리를 계산하여 가장 가까운 점을 찾는다.
|
||||
let adsorptionPoint = findClosestPoint(pointer, adsorptionPoints)
|
||||
|
||||
if (adsorptionPoint && distanceBetweenPoints(pointer, adsorptionPoint) <= adsorptionRange) {
|
||||
arrivalPoint = { ...adsorptionPoint }
|
||||
}
|
||||
|
||||
const horizontalLine = new fabric.Line([-1 * canvas.width, arrivalPoint.y, 2 * canvas.width, arrivalPoint.y], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
name: 'mouseLine',
|
||||
})
|
||||
|
||||
// 세로선
|
||||
const verticalLine = new fabric.Line([arrivalPoint.x, -1 * canvas.height, arrivalPoint.x, 2 * canvas.height], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
name: 'mouseLine',
|
||||
})
|
||||
|
||||
// 선들을 캔버스에 추가합니다.
|
||||
canvas?.add(horizontalLine, verticalLine)
|
||||
|
||||
// 캔버스를 다시 그립니다.
|
||||
canvas?.renderAll()
|
||||
}
|
||||
|
||||
// 보조선 절삭
|
||||
const cutAuxiliary = (e) => {
|
||||
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed)
|
||||
|
||||
if (auxiliaryLines.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
auxiliaryLines.forEach((line1) => {
|
||||
auxiliaryLines.forEach((line2) => {
|
||||
const lines = [line1, line2]
|
||||
if (line1 === line2) {
|
||||
return
|
||||
}
|
||||
|
||||
const intersectionPoint = calculateIntersection(line1, line2)
|
||||
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
|
||||
return
|
||||
}
|
||||
roofAdsorptionPoints.current.push(intersectionPoint)
|
||||
intersectionPoints.current.push(intersectionPoint)
|
||||
lines.forEach((line) => {
|
||||
const distance1 = distanceBetweenPoints({ x: line.x1, y: line.y1 }, intersectionPoint)
|
||||
const distance2 = distanceBetweenPoints({ x: line.x2, y: line.y2 }, intersectionPoint)
|
||||
|
||||
if (distance1 === 0 || distance2 === 0) {
|
||||
return
|
||||
}
|
||||
//historyLine에서 기존 line을 제거한다.
|
||||
lineHistory.current = lineHistory.current.filter((history) => history !== line)
|
||||
|
||||
let newLine
|
||||
|
||||
if (distance1 >= distance2) {
|
||||
newLine = addLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
name: 'auxiliaryLine',
|
||||
isFixed: true,
|
||||
intersectionPoint,
|
||||
})
|
||||
} else {
|
||||
newLine = addLine([line.x2, line.y2, intersectionPoint.x, intersectionPoint.y], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
name: 'auxiliaryLine',
|
||||
isFixed: true,
|
||||
intersectionPoint,
|
||||
})
|
||||
}
|
||||
lineHistory.current.push(newLine)
|
||||
removeLine(line)
|
||||
})
|
||||
})
|
||||
})
|
||||
addCanvasMouseEventListener('mouse:move', mouseMove)
|
||||
}
|
||||
|
||||
/**
|
||||
* 일변전으로 돌아가기
|
||||
*/
|
||||
const handleRollback = () => {
|
||||
const lastLine = lineHistory.current.pop()
|
||||
mousePointerArr.current = []
|
||||
canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'innerPoint'))
|
||||
|
||||
if (lastLine) {
|
||||
roofAdsorptionPoints.current = roofAdsorptionPoints.current.filter(
|
||||
(point) => point.x !== lastLine.intersectionPoint?.x && point.y !== lastLine.intersectionPoint?.y,
|
||||
)
|
||||
|
||||
canvas.remove(lastLine)
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', mouseMove)
|
||||
}
|
||||
|
||||
const handleFix = (fn) => {
|
||||
if (!confirm('지붕선 완료하시겠습니까?')) {
|
||||
return
|
||||
}
|
||||
fn(close)
|
||||
}
|
||||
|
||||
return {
|
||||
length1,
|
||||
setLength1,
|
||||
length2,
|
||||
setLength2,
|
||||
length1Ref,
|
||||
length2Ref,
|
||||
arrow1,
|
||||
setArrow1,
|
||||
arrow2,
|
||||
setArrow2,
|
||||
arrow1Ref,
|
||||
arrow2Ref,
|
||||
angle1,
|
||||
setAngle1,
|
||||
angle1Ref,
|
||||
angle2,
|
||||
setAngle2,
|
||||
angle2Ref,
|
||||
outerLineDiagonalLength,
|
||||
setOuterLineDiagonalLength,
|
||||
outerLineDiagonalLengthRef,
|
||||
type,
|
||||
setType,
|
||||
handleFix,
|
||||
handleRollback,
|
||||
buttonAct,
|
||||
setButtonAct,
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ export function useOuterLineWall() {
|
||||
const adsorptionPointMode = useRecoilValue(adsorptionPointModeState)
|
||||
const adsorptionRange = useRecoilValue(adsorptionRangeState)
|
||||
const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격
|
||||
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
||||
|
||||
const length1Ref = useRef(null)
|
||||
const length2Ref = useRef(null)
|
||||
const angle1Ref = useRef(null)
|
||||
@ -91,23 +91,6 @@ export function useOuterLineWall() {
|
||||
addDocumentEventListener('keydown', document, keydown[type])
|
||||
}, [type])
|
||||
|
||||
useEffect(() => {
|
||||
canvas
|
||||
?.getObjects()
|
||||
.filter((obj) => obj.name !== 'outerLinePoint')
|
||||
.forEach((obj) => canvas.remove(obj))
|
||||
|
||||
const outerLinePoints = canvas?.getObjects().filter((obj) => obj.name === 'outerLinePoint')
|
||||
const newPoints = []
|
||||
if (points.length === 0 && outerLinePoints.length > 0) {
|
||||
outerLinePoints.forEach((point) => {
|
||||
newPoints.push({ x: point.left, y: point.top })
|
||||
})
|
||||
|
||||
setPoints(newPoints)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const clear = () => {
|
||||
setLength1(0)
|
||||
setLength2(0)
|
||||
@ -490,6 +473,14 @@ export function useOuterLineWall() {
|
||||
//대각선 완료될 경우 확인
|
||||
const checkDiagonal = (direction) => {
|
||||
const activeElem = document.activeElement
|
||||
const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이
|
||||
|
||||
const length1Value = length1Ref.current.value
|
||||
|
||||
if (diagonalLength <= length1Value) {
|
||||
alert('대각선 길이는 직선 길이보다 길어야 합니다.')
|
||||
return
|
||||
}
|
||||
|
||||
const canDirection =
|
||||
direction === '↓' || direction === '↑'
|
||||
@ -507,10 +498,6 @@ export function useOuterLineWall() {
|
||||
arrow2Ref.current = direction
|
||||
}
|
||||
|
||||
const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이
|
||||
|
||||
const length1Value = length1Ref.current.value
|
||||
|
||||
const arrow1Value = arrow1Ref.current
|
||||
const arrow2Value = arrow2Ref.current
|
||||
|
||||
@ -672,6 +659,8 @@ export function useOuterLineWall() {
|
||||
case 'ArrowRight':
|
||||
checkRightAngle('→')
|
||||
break
|
||||
case 'Enter':
|
||||
break
|
||||
}
|
||||
},
|
||||
doublePitch: (e) => {
|
||||
|
||||
@ -30,17 +30,6 @@ export function useRoofShapeSetting() {
|
||||
|
||||
const history = useRef([])
|
||||
|
||||
useEffect(() => {
|
||||
const wallLine = canvas.getObjects().find((obj) => obj.name === 'wallLine')
|
||||
canvas?.remove(wallLine)
|
||||
|
||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||
outerLines.forEach((line) => {
|
||||
showLine(line)
|
||||
})
|
||||
canvas?.renderAll()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (shapeNum !== 4) {
|
||||
return
|
||||
@ -118,9 +107,6 @@ export function useRoofShapeSetting() {
|
||||
|
||||
let outerLines
|
||||
|
||||
canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'wallLine'))
|
||||
canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'roofBase'))
|
||||
|
||||
switch (shapeNum) {
|
||||
case 1: {
|
||||
outerLines = saveRidge()
|
||||
|
||||
@ -21,6 +21,10 @@ export function useEvent() {
|
||||
const textMode = useRecoilValue(textModeState)
|
||||
|
||||
useEffect(() => {
|
||||
initEvent()
|
||||
}, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting, tempGridMode])
|
||||
|
||||
const initEvent = () => {
|
||||
if (!canvas) {
|
||||
return
|
||||
}
|
||||
@ -33,7 +37,7 @@ export function useEvent() {
|
||||
canvas?.on('mouse:wheel', wheelEvent)
|
||||
|
||||
addDefaultEvent()
|
||||
}, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting, tempGridMode])
|
||||
}
|
||||
|
||||
const addDefaultEvent = () => {
|
||||
//default Event 추가
|
||||
@ -234,8 +238,7 @@ export function useEvent() {
|
||||
const removeDocumentEvent = (type) => {
|
||||
documentEventListeners.current = documentEventListeners.current.filter((event) => {
|
||||
if (event.eventType === type) {
|
||||
console.log(type)
|
||||
event.element.removeEventListener(type, event.handler)
|
||||
document.removeEventListener(event.eventType, event.handler)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -248,5 +251,7 @@ export function useEvent() {
|
||||
removeAllMouseEventListeners,
|
||||
removeAllDocumentEventListeners,
|
||||
removeMouseEvent,
|
||||
removeMouseLine,
|
||||
initEvent,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user