diff --git a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx index e144e717..8a8da385 100644 --- a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx +++ b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx @@ -5,16 +5,35 @@ import Eaves from '@/components/floor-plan/modal/eavesGable/type/Eaves' import Gable from '@/components/floor-plan/modal/eavesGable/type/Gable' import WallMerge from '@/components/floor-plan/modal/eavesGable/type/WallMerge' import Shed from '@/components/floor-plan/modal/eavesGable/type/Shed' +import { useEavesGableEdit } from '@/hooks/roofcover/useEavesGableEdit' export default function EavesGableEdit({ setShowEavesGableEditModal }) { const { getMessage } = useMessage() - const [buttonAct, setButtonAct] = useState(1) - const buttonMenu = [ - { id: 1, name: getMessage('eaves') }, - { id: 2, name: getMessage('gable') }, - { id: 3, name: getMessage('wall.merge') }, - { id: 4, name: getMessage('shed') }, - ] + + const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit() + const eavesProps = { + pitchRef, + offsetRef, + widthRef, + radioTypeRef, + } + + const gableProps = { + pitchRef, + offsetRef, + widthRef, + radioTypeRef, + } + + const wallMergeProps = { + offsetRef, + radioTypeRef, + } + + const shedProps = { + offsetRef, + } + return (
@@ -27,17 +46,17 @@ export default function EavesGableEdit({ setShowEavesGableEditModal }) {
{buttonMenu.map((item) => ( - ))}
{getMessage('setting')}
- {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } - {buttonAct === 4 && } + {type === TYPES.EAVES && } + {type === TYPES.GABLE && } + {type === TYPES.WALL_MERGE && } + {type === TYPES.SHED && }
diff --git a/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx b/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx index 37ffd5e9..80120107 100644 --- a/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx +++ b/src/components/floor-plan/modal/eavesGable/type/Eaves.jsx @@ -2,12 +2,12 @@ import { useMessage } from '@/hooks/useMessage' import Image from 'next/image' import { useState } from 'react' -export default function Eaves() { +export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) { const { getMessage } = useMessage() - const [type, setType] = useState() + const [type, setType] = useState('1') const onChange = (e) => { - console.log(e) setType(e.target.value) + radioTypeRef.current = e.target.value } return ( <> @@ -17,7 +17,7 @@ export default function Eaves() { {getMessage('slope')}
- +
@@ -26,7 +26,7 @@ export default function Eaves() { {getMessage('offset')}
- +
mm @@ -63,7 +63,7 @@ export default function Eaves() {
- +
mm
diff --git a/src/components/floor-plan/modal/eavesGable/type/Gable.jsx b/src/components/floor-plan/modal/eavesGable/type/Gable.jsx index 03a35f32..23f9c300 100644 --- a/src/components/floor-plan/modal/eavesGable/type/Gable.jsx +++ b/src/components/floor-plan/modal/eavesGable/type/Gable.jsx @@ -1,8 +1,14 @@ import { useMessage } from '@/hooks/useMessage' import Image from 'next/image' +import { useState } from 'react' -export default function Gable() { +export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) { const { getMessage } = useMessage() + const [type, setType] = useState('1') + const onChange = (e) => { + setType(e.target.value) + radioTypeRef.current = e.target.value + } return ( <>
@@ -11,7 +17,7 @@ export default function Gable() { {getMessage('offset')}
- +
mm
@@ -21,12 +27,12 @@ export default function Gable() {
- + onChange(e)} />
-
+
react
@@ -34,12 +40,12 @@ export default function Gable() {
- + onChange(e)} />
-
+
react
@@ -51,7 +57,7 @@ export default function Gable() { {getMessage('slope')}
- +
@@ -69,7 +75,7 @@ export default function Gable() { {getMessage('offset')}
- +
mm
diff --git a/src/components/floor-plan/modal/eavesGable/type/Shed.jsx b/src/components/floor-plan/modal/eavesGable/type/Shed.jsx index ebf20417..436316a3 100644 --- a/src/components/floor-plan/modal/eavesGable/type/Shed.jsx +++ b/src/components/floor-plan/modal/eavesGable/type/Shed.jsx @@ -1,6 +1,6 @@ import { useMessage } from '@/hooks/useMessage' -export default function Shed() { +export default function Shed({ offsetRef }) { const { getMessage } = useMessage() return ( <> @@ -10,7 +10,7 @@ export default function Shed() { {getMessage('offset')}
- +
mm
diff --git a/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx index fbc335e6..0f80f9ec 100644 --- a/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx +++ b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx @@ -1,8 +1,14 @@ import { useMessage } from '@/hooks/useMessage' import Image from 'next/image' +import { useState } from 'react' -export default function WallMerge() { +export default function WallMerge({ offsetRef, radioTypeRef }) { const { getMessage } = useMessage() + const [type, setType] = useState('1') + const onChange = (e) => { + setType(e.target.value) + radioTypeRef.current = e.target.value + } return ( <>
@@ -11,12 +17,12 @@ export default function WallMerge() {
- + onChange(e)} />
-
+
react
@@ -24,12 +30,12 @@ export default function WallMerge() {
- + onChange(e)} />
-
+
react
@@ -41,7 +47,7 @@ export default function WallMerge() { {getMessage('offset')}
- +
mm
diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js new file mode 100644 index 00000000..49943c04 --- /dev/null +++ b/src/hooks/roofcover/useEavesGableEdit.js @@ -0,0 +1,204 @@ +import { useEffect, useRef, useState } from 'react' +import { useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { useMessage } from '@/hooks/useMessage' +import { useEvent } from '@/hooks/useEvent' +import { LINE_TYPE } from '@/common/common' +import { useLine } from '@/hooks/useLine' +import { useMode } from '@/hooks/useMode' + +export function useEavesGableEdit() { + const canvas = useRecoilValue(canvasState) + const { getMessage } = useMessage() + const { addCanvasMouseEventListener, initEvent } = useEvent() + const TYPES = { + EAVES: 'eaves', + GABLE: 'gable', + WALL_MERGE: 'wall.merge', + SHED: 'shed', + } + const [type, setType] = useState(TYPES.EAVES) + const typeRef = useRef(TYPES.EAVES) + const { removeLine } = useLine() + + const { drawRoofPolygon } = useMode() + + const pitchRef = useRef(null) + const offsetRef = useRef(null) + const widthRef = useRef(null) + const radioTypeRef = useRef('1') // 각 페이지에서 사용하는 radio type + + const buttonMenu = [ + { id: 1, name: getMessage('eaves'), type: TYPES.EAVES }, + { id: 2, name: getMessage('gable'), type: TYPES.GABLE }, + { id: 3, name: getMessage('wall.merge'), type: TYPES.WALL_MERGE }, + { id: 4, name: getMessage('shed'), type: TYPES.SHED }, + ] + + useEffect(() => { + const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') + wallLines.forEach((wallLine) => { + convertPolygonToLines(wallLine) + }) + + addCanvasMouseEventListener('mouse:over', mouseOverEvent) + addCanvasMouseEventListener('mouse:down', mouseDownEvent) + + return () => { + wallLines.forEach((wallLine) => { + convertLinesToPolygon(wallLine) + }) + initEvent() + } + }, []) + + useEffect(() => { + typeRef.current = type + }, [type]) + + const mouseOverEvent = (e) => { + if (e.target && e.target.name === 'outerLine') { + e.target.set({ + stroke: 'red', + }) + canvas.renderAll() + } else { + canvas + ?.getObjects() + .filter((obj) => obj.name === 'outerLine') + .forEach((line) => { + line.set({ + stroke: 'black', + }) + }) + } + canvas.renderAll() + } + + const mouseDownEvent = (e) => { + if (!e.target || (e.target && e.target.name !== 'outerLine')) { + return + } + + const target = e.target + + let attributes = target.get('attributes') + + switch (typeRef.current) { + case TYPES.EAVES: + if (radioTypeRef.current === '1') { + attributes = { + type: LINE_TYPE.WALLLINE.EAVES, + pitch: pitchRef.current.value, + offset: offsetRef.current.value / 10, + } + } else { + attributes = { + type: LINE_TYPE.WALLLINE.HIPANDGABLE, + pitch: pitchRef.current.value, + offset: offsetRef.current.value / 10, + width: widthRef.current.value / 10, + } + } + break + case TYPES.GABLE: + if (radioTypeRef.current === '1') { + attributes = { + type: LINE_TYPE.WALLLINE.GABLE, + offset: offsetRef.current.value / 10, + } + } else { + attributes = { + type: LINE_TYPE.WALLLINE.JERKINHEAD, + pitch: pitchRef.current.value, + offset: offsetRef.current.value / 10, + width: widthRef.current.value / 10, + } + } + break + case TYPES.WALL_MERGE: + if (radioTypeRef.current === '1') { + attributes = { + type: LINE_TYPE.WALLLINE.WALL, + offset: 0, + } + } else { + attributes = { + type: LINE_TYPE.WALLLINE.WALL, + offset: offsetRef.current.value / 10, + } + } + break + case TYPES.SHED: + attributes = { + type: LINE_TYPE.WALLLINE.SHED, + offset: offsetRef.current.value / 10, + } + break + } + + target.set({ + attributes, + }) + + const roofBases = canvas?.getObjects().filter((obj) => obj.name === 'roofBase') + + roofBases.forEach((roof) => { + roof.innerLines.forEach((line) => { + removeLine(line) + }) + canvas.remove(roof) + }) + + const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') + + wallLines.forEach((wallLine) => { + const roof = drawRoofPolygon(wallLine) + + canvas?.renderAll() + roof.drawHelpLine() + }) + + wallLines.forEach((wallLine) => { + convertPolygonToLines(wallLine) + }) + + addCanvasMouseEventListener('mouse:over', mouseOverEvent) + addCanvasMouseEventListener('mouse:down', mouseDownEvent) + } + + // polygon의 lines를 이용해 line으로 변경하기 + const convertPolygonToLines = (polygon) => { + polygon.set({ visible: false }) + polygon.lines.forEach((line) => { + line.set({ visible: true }) + line.set({ selectable: true }) + line.set({ strokeWidth: 5 }) + line.set({ parent: polygon }) + line.bringToFront() + }) + + // canvas objects에서 polygon.lines를 제외한 다른 line의 selectable을 false로 변경 + canvas + .getObjects() + .filter((obj) => obj.name !== 'outerLine' && obj.type === 'QLine') + .forEach((obj) => { + obj.set({ selectable: false }) + }) + + canvas?.renderAll() + } + + // 다시 다각형으로 변경하기 + const convertLinesToPolygon = (polygon) => { + polygon.set({ visible: true }) + polygon.lines.forEach((line) => { + line.set({ visible: false }) + line.set({ selectable: false }) + }) + + canvas?.renderAll() + } + + return { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } +}