qcast-front/src/hooks/roofcover/useMovementSetting.js
2024-12-12 13:38:36 +09:00

381 lines
13 KiB
JavaScript

import { useRecoilValue } from 'recoil'
import { canvasState, currentObjectState } from '@/store/canvasAtom'
import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useRef, useState } from 'react'
import { useEvent } from '@/hooks/useEvent'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import { getDegreeByChon } from '@/util/canvas-util'
//동선이동 형 올림 내림
export function useMovementSetting(id) {
const TYPE = {
FLOW_LINE: 'flowLine', // 동선이동
UP_DOWN: 'updown', //형 올림내림
}
const canvas = useRecoilValue(canvasState)
const { initEvent, addCanvasMouseEventListener } = useEvent()
// const { initEvent, addCanvasMouseEventListener } = useContext(EventContext)
const { closePopup } = usePopup()
const { getMessage } = useMessage()
const currentObject = useRecoilValue(currentObjectState)
const selectedObject = useRef(null)
const buttonType = [
{ id: 1, name: getMessage('modal.movement.flow.line.move'), type: TYPE.FLOW_LINE },
{ id: 2, name: getMessage('modal.movement.flow.line.updown'), type: TYPE.UP_DOWN },
]
const [type, setType] = useState(TYPE.FLOW_LINE)
const typeRef = useRef(type)
const FLOW_LINE_REF = {
POINTER_INPUT_REF: useRef(null),
FILLED_INPUT_REF: useRef(null),
DOWN_LEFT_RADIO_REF: useRef(null),
UP_RIGHT_RADIO_REF: useRef(null),
}
const UP_DOWN_REF = {
UP_INPUT_REF: useRef(null),
DOWN_INPUT_REF: useRef(null),
UP_RADIO_REF: useRef(null),
DOWN_RADIO_REF: useRef(null),
}
useEffect(() => {
typeRef.current = type
canvas.getObjects().forEach((obj) => {
obj.set({ selectable: false })
})
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // 기존 wallLine의 visible false
roofs.forEach((roof) => {
roof.set({ selectable: false })
roof.set({ strokeWidth: 1 })
roof.set({ stroke: '#000000' })
roof.innerLines.forEach((line) => {
line.bringToFront()
line.set({ selectable: false })
line.set({ strokeWidth: 1 })
line.set({ stroke: '#000000' })
})
roof.separatePolygon?.forEach((polygon) => {
polygon.bringToFront()
polygon.set({ selectable: false })
polygon.set({ strokeWidth: 1 })
polygon.set({ stroke: '#000000' })
})
})
if (type === TYPE.FLOW_LINE) {
roofs.forEach((roof) => {
roof.innerLines.forEach((line) => {
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
line.bringToFront()
line.set({ selectable: true })
line.set({ strokeWidth: 4 })
line.set({ stroke: '#1083E3' })
}
})
})
} else if (type === TYPE.UP_DOWN) {
const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
wallLine.forEach((line) => {
line.bringToFront()
line.set({ selectable: true })
})
}
canvas.renderAll()
}, [type])
useEffect(() => {
canvas.renderAll()
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
return () => {
initEvent()
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
wallLines.forEach((line) => {
line.set({ visible: true })
})
const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
wallLine.forEach((line) => {
let wallStroke, wallStrokeWidth
switch (line.attributes.type) {
case LINE_TYPE.WALLLINE.EAVES:
wallStroke = '#45CD7D'
wallStrokeWidth = 4
break
case LINE_TYPE.WALLLINE.HIPANDGABLE:
wallStroke = '#45CD7D'
wallStrokeWidth = 4
break
case LINE_TYPE.WALLLINE.GABLE:
wallStroke = '#3FBAE6'
wallStrokeWidth = 4
break
case LINE_TYPE.WALLLINE.JERKINHEAD:
wallStroke = '#3FBAE6'
wallStrokeWidth = 4
break
case LINE_TYPE.WALLLINE.SHED:
wallStroke = '#000000'
wallStrokeWidth = 4
break
case LINE_TYPE.WALLLINE.WALL:
wallStroke = '#000000'
wallStrokeWidth = 4
break
}
line.set({ selectable: false, stroke: wallStroke, strokeWidth: wallStrokeWidth })
})
canvas.renderAll()
}
}, [])
useEffect(() => {
selectedObject.current = null
if (!currentObject) {
return
}
clearRef()
selectedObject.current = currentObject
if (currentObject.name === 'wallLine') {
currentObject.set({ stroke: '#EA10AC' })
currentObject.bringToFront()
}
canvas.renderAll()
}, [currentObject])
const clearRef = () => {
if (type === TYPE.FLOW_LINE) {
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = false
}
if (type === TYPE.UP_DOWN) {
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = false
}
}
const mouseDownEvent = (e) => {
if (typeRef.current === TYPE.FLOW_LINE) {
saveFlowLine(e)
} else {
updownDownEvent(e)
}
}
const mouseMoveEvent = (e) => {
if (typeRef.current === TYPE.FLOW_LINE) {
flowLineMoveEvent(e)
} else {
updownMoveEvent(e)
}
}
//동선 이동 마우스 클릭 이벤트
const saveFlowLine = (e) => {
const target = selectedObject.current
if (!target) {
return
}
let newPoint = []
if (Math.sign(target.x1 - target.x2) !== 0) {
newPoint = [
target.x1,
target.y1 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
target.x2,
target.y2 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
]
} else {
newPoint = [
target.x1 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
target.y1,
target.x2 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
target.y2,
]
}
clearRef()
const cloned = new fabric.Line(newPoint, {})
let currentObject = selectedObject.current
const currentX1 = currentObject.x1,
currentY1 = currentObject.y1,
currentX2 = currentObject.x2,
currentY2 = currentObject.y2
const roof = canvas.getObjects().find((obj) => obj.id === currentObject.attributes.roofId)
if (roof.separatePolygon.length > 0) {
const separatePolygon = roof.separatePolygon
separatePolygon
.filter((polygon) =>
polygon.points.some((point) => (point.x === currentX1 && point.y === currentY1) || (point.x === currentX2 && point.y === currentY2)),
)
.forEach((polygon) => {
const newPoints = polygon.points.map((point) => {
if (point.x === currentX1 && point.y === currentY1) {
return { x: newPoint[0], y: newPoint[1] }
} else if (point.x === currentX2 && point.y === currentY2) {
return { x: newPoint[2], y: newPoint[3] }
} else {
return point
}
})
polygon.set({ points: newPoints })
polygon.setCoords()
polygon.addLengthText()
polygon.initLines()
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
const currentDegree = polygon.attributes.pitch > 0 ? getDegreeByChon(polygon.attributes.pitch) : polygon.attributes.degree
polygon.lines.forEach((line) => {
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
if (currentDegree > 0 && slope(line) !== slope(currentObject)) {
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
} else {
line.attributes.actualSize = line.attributes.planeSize
}
})
})
} else {
roof.innerLines
.filter((line) => currentObject !== line)
.filter(
(line) =>
(line.x1 === currentX1 && line.y1 === currentY1) ||
(line.x2 === currentX1 && line.y2 === currentY1) ||
(line.x1 === currentX2 && line.y1 === currentY2) ||
(line.x2 === currentX2 && line.y2 === currentY2),
)
.forEach((line) => {
const lineDegree = 90 - Math.asin(line.attributes.planeSize / line.attributes.actualSize) * (180 / Math.PI)
if (line.x1 === currentX1 && line.y1 === currentY1) {
line.set({ x1: newPoint[0], y1: newPoint[1] })
} else if (line.x2 === currentX1 && line.y2 === currentY1) {
line.set({ x2: newPoint[0], y2: newPoint[1] })
} else if (line.x1 === currentX2 && line.y1 === currentY2) {
line.set({ x1: newPoint[2], y1: newPoint[3] })
} else if (line.x2 === currentX2 && line.y2 === currentY2) {
line.set({ x2: newPoint[2], y2: newPoint[3] })
}
line.setCoords()
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
line.attributes.actualSize = Math.round(
Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(line.attributes.planeSize * Math.tan(lineDegree * (Math.PI / 180)), 2)),
)
})
}
currentObject.set({ x1: cloned.x1, y1: cloned.y1, x2: cloned.x2, y2: cloned.y2 })
currentObject.setCoords()
canvas.renderAll()
canvas.discardActiveObject()
}
//형 올림내림 마우스 클릭 이벤트
const updownDownEvent = (e) => {
console.log('updownDownEvent')
}
const flowLineMoveEvent = (e) => {
const target = canvas.getActiveObject()
if (!target) {
return
}
const { top: targetTop, left: targetLeft } = target
const currentX = canvas.getPointer(e.e).x
const currentY = Math.floor(canvas.getPointer(e.e).y)
if (Math.sign(target.x1 - target.x2) !== 0) {
if (targetTop > currentY) {
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
} else {
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
}
} else {
if (targetLeft > currentX) {
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
} else {
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
}
}
canvas?.renderAll()
}
const updownMoveEvent = (e) => {
const target = canvas.getActiveObject()
if (!target) {
return
}
const direction = target.direction
const { top: targetTop, left: targetLeft } = target
const currentX = canvas.getPointer(e.e).x
const currentY = Math.floor(canvas.getPointer(e.e).y)
if (direction === 'left' || direction === 'right') {
if (targetTop > currentY) {
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = true
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
UP_DOWN_REF.DOWN_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
} else {
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
UP_DOWN_REF.UP_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
}
} else {
if (targetLeft > currentX) {
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = true
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
UP_DOWN_REF.DOWN_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
} else {
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
UP_DOWN_REF.UP_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
}
}
canvas?.renderAll()
}
const handleSave = () => {
if (type === TYPE.FLOW_LINE) {
saveFlowLine()
} else {
// 형 올림내림
if (UP_DOWN_REF.UP_RADIO_REF.current.checked) {
// 자릿수를 올리다 체크
const length = Number(UP_DOWN_REF.UP_INPUT_REF.current.value)
} else {
// 자릿수를 내리다 체크
const length = Number(UP_DOWN_REF.DOWN_INPUT_REF.current.value)
}
}
}
return {
TYPE,
closePopup,
buttonType,
type,
setType,
FLOW_LINE_REF,
UP_DOWN_REF,
handleSave,
}
}