From 0bf1fbfe5683d1faf6a833c1d7404f7a48e1643f Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 30 Sep 2024 14:48:02 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=3D>=20=EC=99=B8=EB=B2=BD=EC=84=A0=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=84=A4=EC=A0=95=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 3 +- src/components/floor-plan/FloorPlan.jsx | 1 + .../modal/outerlinesetting/Angle.jsx | 39 +- .../modal/outerlinesetting/Diagonal.jsx | 128 +++++- .../modal/outerlinesetting/DoublePitch.jsx | 173 +++++++- .../modal/outerlinesetting/OuterLineWall.jsx | 40 +- ...ertiesSetting.js => PropertiesSetting.jsx} | 21 +- .../modal/outerlinesetting/RightAngle.jsx | 101 ++++- .../outerlinesetting/WallLineSetting.jsx | 115 +++++- src/hooks/roofcover/useOuterLineWall.js | 371 ++++++++++++++---- src/hooks/roofcover/usePropertiesSetting.js | 89 +++++ src/hooks/useAdsorptionPoint.js | 2 +- src/hooks/useCanvas.js | 9 +- src/hooks/useDotLineGrid.js | 1 + src/hooks/useEvent.js | 44 ++- src/hooks/useLine.js | 1 + 16 files changed, 974 insertions(+), 164 deletions(-) rename src/components/floor-plan/modal/outerlinesetting/{PropertiesSetting.js => PropertiesSetting.jsx} (56%) create mode 100644 src/hooks/roofcover/usePropertiesSetting.js diff --git a/src/common/common.js b/src/common/common.js index 84cf60a3..f9ca6fff 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -53,8 +53,9 @@ export const Mode = { export const LINE_TYPE = { WALLLINE: { /** - * 처마 / 캐라바 / 벽 / 팔작지붕 / 반절처 / 한쪽흐름 + * 없음 / 처마 / 캐라바 / 벽 / 팔작지붕 / 반절처 / 한쪽흐름 */ + DEFAULT: 'default', EAVES: 'eaves', GABLE: 'gable', WALL: 'wall', diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 9f7c6641..55b700c1 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -34,6 +34,7 @@ export default function FloorPlan() { const outlineProps = { setShowOutlineModal, + setShowPropertiesSettingModal, } const modalProps = { diff --git a/src/components/floor-plan/modal/outerlinesetting/Angle.jsx b/src/components/floor-plan/modal/outerlinesetting/Angle.jsx index ca3ea288..83985016 100644 --- a/src/components/floor-plan/modal/outerlinesetting/Angle.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/Angle.jsx @@ -1,8 +1,11 @@ import Image from 'next/image' import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' -export default function Angle() { +export default function Angle({ props }) { const { getMessage } = useMessage() + const { angle1, setAngle1, angle1Ref, length1, setLength1, length1Ref } = props + return ( <>
@@ -11,16 +14,40 @@ export default function Angle() {
{getMessage('modal.cover.outline.angle')}
- + onlyNumberWithDotInputChange(e, setAngle1)} + placeholder="45" + />
- +
- {getMessage('modal.cover.outline.arrow')} + {getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
diff --git a/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx b/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx index 9ae9f02e..84c25329 100644 --- a/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/Diagonal.jsx @@ -1,7 +1,24 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function Diagonal() { +export default function Diagonal({ props }) { const { getMessage } = useMessage() + + const { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } = props return ( <>
@@ -13,26 +30,77 @@ export default function Diagonal() { {getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setOuterLineDiagonalLength)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -40,16 +108,48 @@ export default function Diagonal() {
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + readOnly={true} + placeholder="3000" + />
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx b/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx index ea386d4b..5bfa5950 100644 --- a/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/DoublePitch.jsx @@ -1,7 +1,48 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' +import { getDegreeByChon } from '@/util/canvas-util' -export default function DoublePitch() { +export default function DoublePitch({ props }) { const { getMessage } = useMessage() + const { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } = props + + const getLength2 = () => { + const angle1Value = angle1Ref.current.value + const angle2Value = angle2Ref.current.value + const length1Value = length1Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '') { + const radian1 = (getDegreeByChon(angle1Value) * Math.PI) / 180 + + const radian2 = (getDegreeByChon(angle2Value) * Math.PI) / 180 + return Math.floor((Math.tan(radian1) * length1Value) / Math.tan(radian2)) + } + + return 0 + } + return ( <>
@@ -9,26 +50,70 @@ export default function DoublePitch() {
{getMessage('modal.cover.outline.angle')}
- + onlyNumberWithDotInputChange(e, setAngle1)} + placeholder="45" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -38,26 +123,80 @@ export default function DoublePitch() {
{getMessage('modal.cover.outline.angle')}
- + { + onlyNumberWithDotInputChange(e, setAngle2) + console.log(getLength2()) + setLength2(getLength2()) + }} + placeholder="45" + />
- +
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + readOnly={true} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx index 9dfa85c8..a3493f17 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx @@ -1,12 +1,12 @@ 'use client' import { useMessage } from '@/hooks/useMessage' -import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall' import { onlyNumberInputChange } from '@/util/input-utils' -export default function OuterLineWall(props) { +export default function OuterLineWall({ props }) { const { getMessage } = useMessage() - const { length1, setLength1, length1Ref, arrow1, setArrow1 } = useOuterLineWall() + + const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props return (
@@ -22,15 +22,39 @@ export default function OuterLineWall(props) { placeholder="3000" />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx similarity index 56% rename from src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js rename to src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index c4950666..0120f6a4 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -1,10 +1,13 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { useMessage } from '@/hooks/useMessage' +import { usePropertiesSetting } from '@/hooks/roofcover/usePropertiesSetting' export default function PropertiesSetting(props) { const { getMessage } = useMessage() const { setShowPropertiesSettingModal } = props - + + const { handleSetEaves, handleSetGable, handleRollback, handleFix } = usePropertiesSetting() + return (
@@ -19,13 +22,21 @@ export default function PropertiesSetting(props) {
{getMessage('setting')}
- - + +
- - + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx b/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx index 815ab087..306a09f0 100644 --- a/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/RightAngle.jsx @@ -1,24 +1,63 @@ import { useMessage } from '@/hooks/useMessage' +import { onlyNumberInputChange } from '@/util/input-utils' -export default function RightAngle() { +export default function RightAngle({ props }) { const { getMessage } = useMessage() + const { length1, setLength1, length1Ref, length2, setLength2, length2Ref, arrow1, setArrow1, arrow2, setArrow2 } = props return (
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength1)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
@@ -26,17 +65,53 @@ export default function RightAngle() {
{getMessage('modal.cover.outline.length')}
- + onlyNumberInputChange(e, setLength2)} + placeholder="3000" + />
- +
{getMessage('modal.cover.outline.arrow')}
- - - - + + + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index 0cba88c2..8a9c1979 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -11,9 +11,102 @@ import DoublePitch from '@/components/floor-plan/modal/outerlinesetting/DoublePi import Diagonal from '@/components/floor-plan/modal/outerlinesetting/Diagonal' export default function WallLineSetting(props) { - const { setShowOutlineModal } = props + const { setShowOutlineModal, setShowPropertiesSettingModal } = props const { getMessage } = useMessage() - const { type, setType, handleFix, handleRollback } = useOuterLineWall() + const { + length1, + setLength1, + length2, + setLength2, + length1Ref, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + type, + setType, + arrow1Ref, + arrow2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + handleRollback, + handleFix, + } = useOuterLineWall() + + const outerLineProps = { + length1, + setLength1, + length1Ref, + arrow1, + setArrow1, + } + + const rightAngleProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + } + + const doublePitchProps = { + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + arrow1, + setArrow1, + arrow2, + setArrow2, + arrow1Ref, + arrow2Ref, + } + + const angleProps = { + angle1, + setAngle1, + angle1Ref, + length1, + setLength1, + length1Ref, + } + + const diagonalLineProps = { + length1, + setLength1, + length1Ref, + length2, + setLength2, + length2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, + arrow1, + setArrow1, + arrow2, + setArrow2, + } return ( @@ -58,15 +151,15 @@ export default function WallLineSetting(props) {
{getMessage('modal.cover.outline.setting')}
{type === OUTER_LINE_TYPE.OUTER_LINE ? ( - + ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( - + ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( - + ) : type === OUTER_LINE_TYPE.ANGLE ? ( - + ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( - + ) : ( <> )} @@ -75,7 +168,13 @@ export default function WallLineSetting(props) { -
diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 355eca16..0f1e4f41 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -1,5 +1,5 @@ import { useEffect, useRef } from 'react' -import { distanceBetweenPoints } from '@/util/canvas-util' +import { distanceBetweenPoints, getDegreeByChon } from '@/util/canvas-util' import { useRecoilState, useRecoilValue } from 'recoil' import { adsorptionPointAddModeState, @@ -16,14 +16,17 @@ import { useTempGrid } from '@/hooks/useTempGrid' import { usePolygon } from '@/hooks/usePolygon' import { outerLineAngle1State, + outerLineAngle2State, outerLineArrow1State, outerLineArrow2State, + outerLineDiagonalState, outerLineLength1State, outerLineLength2State, outerLinePointsState, outerLineTypeState, } from '@/store/outerLineAtom' import { calculateAngle } from '@/util/qpolygon-utils' +import { fabric } from 'fabric' export function useOuterLineWall() { const canvas = useRecoilValue(canvasState) @@ -33,6 +36,7 @@ export function useOuterLineWall() { const { addLine, removeLine } = useLine() const { tempGridMode } = useTempGrid() const { addPolygonByLines } = usePolygon() + const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) @@ -42,28 +46,31 @@ export function useOuterLineWall() { const length1Ref = useRef(null) const length2Ref = useRef(null) const angle1Ref = useRef(null) + const angle2Ref = 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 [angle1, setAngle1] = useRecoilState(outerLineAngle1State) + const [angle2, setAngle2] = useRecoilState(outerLineAngle2State) + const [outerLineDiagonalLength, setOuterLineDiagonalLength] = useRecoilState(outerLineDiagonalState) const arrow1Ref = useRef(arrow1) const arrow2Ref = useRef(arrow2) + const outerLineDiagonalLengthRef = useRef(null) + const isFix = useRef(false) - const [angle1, setAngle1] = useRecoilState(outerLineAngle1State) + const closeModalFn = useRef(null) + useEffect(() => { if (adsorptionPointAddMode || tempGridMode) { return } - removeMouseEvent('mouse:down', mouseDown) addCanvasMouseEventListener('mouse:down', mouseDown) clear() - return () => { - removeAllMouseEventListeners() - } }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) useEffect(() => { @@ -75,9 +82,8 @@ export function useOuterLineWall() { }, [arrow2]) useEffect(() => { - removeAllDocumentEventListeners() - addDocumentEventListener('keydown', document, keydown[type]) clear() + addDocumentEventListener('keydown', document, keydown[type]) }, [type]) const clear = () => { @@ -88,6 +94,9 @@ export function useOuterLineWall() { setArrow2('') setAngle1(0) + setAngle2(0) + + setOuterLineDiagonalLength(0) } const mouseDown = (e) => { @@ -143,14 +152,13 @@ export function useOuterLineWall() { canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) - // point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록 - removeAllDocumentEventListeners() - addDocumentEventListener('keydown', document, keydown[type]) - if (points.length === 0) { + removeAllDocumentEventListeners() return } + addDocumentEventListener('keydown', document, keydown[type]) + if (points.length === 1) { const point = new fabric.Circle({ radius: 5, @@ -174,6 +182,13 @@ export function useOuterLineWall() { const lastPoint = points[points.length - 1] const firstPoint = points[0] + if (isFix.current) { + canvas?.renderAll() + closeModalFn.current(false) + removeAllMouseEventListeners() + removeAllDocumentEventListeners() + } + if (points.length < 3) { return } @@ -241,7 +256,7 @@ export function useOuterLineWall() { stroke: 'black', strokeWidth: 3, idx: idx, - selectable: false, + selectable: true, name: 'outerLine', }) } @@ -261,7 +276,26 @@ export function useOuterLineWall() { } // 직각 완료될 경우 확인 - const checkRightAngle = () => { + 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 @@ -332,6 +366,191 @@ export function useOuterLineWall() { } } + //이구배 완료될 경우 확인 ↓, ↑, ←, → + 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 = angle1Ref.current.value + const angle2Value = angle2Ref.current.value + const length1Value = length1Ref.current.value + const length2Value = length2Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') { + if (arrow1Value === '↓' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '↓' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '←' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '←' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } + + angle1Ref.current.focus() + } + } + + //대각선 완료될 경우 확인 + const checkDiagonal = (direction) => { + const activeElem = document.activeElement + + 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 diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이 + + const length1Value = length1Ref.current.value + + const arrow1Value = arrow1Ref.current + const arrow2Value = arrow2Ref.current + + const getLength2 = () => { + return Math.floor(Math.sqrt(diagonalLength ** 2 - length1Value ** 2)) + } + + const length2Value = getLength2() + + console.log(length2Value) + + if (diagonalLength !== 0 && length1Value !== 0 && arrow1Value !== '') { + setLength2(getLength2()) + length2Ref.current.focus() + } + + if (length1Value !== 0 && length2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') { + if (arrow1Value === '↓' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '↓' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '→') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '↑' && arrow2Value === '←') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↓') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }] + }) + } else if (arrow1Value === '→' && arrow2Value === '↑') { + setPoints((prev) => { + if (prev.length === 0) { + return [] + } + return [ + ...prev, + { + x: prev[prev.length - 1].x + length1Value / 10, + y: prev[prev.length - 1].y - length2Value / 10, + }, + ] + }) + } + } + } + const keydown = { outerLine: (e) => { if (points.length === 0) { @@ -411,75 +630,52 @@ export function useOuterLineWall() { 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() - } - + 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() - } - + 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() - } - + 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() - } - + checkRightAngle('→') break } }, - leeGubae: (e) => { - console.log('leegubae') + doublePitch: (e) => { + if (points.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 (points.length === 0) { + return + } const key = e.key switch (key) { case 'Enter': { @@ -501,7 +697,30 @@ export function useOuterLineWall() { } }, diagonalLine: (e) => { - console.log('diagonalLine') + if (points.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 + } }, } @@ -513,7 +732,7 @@ export function useOuterLineWall() { setPoints((prev) => prev.slice(0, prev.length - 1)) } - const handleFix = () => { + const handleFix = (fn) => { if (points.length < 3) { return } @@ -541,6 +760,9 @@ export function useOuterLineWall() { setPoints((prev) => { return [...prev, { x: prev[0].x, y: prev[0].y }] }) + + isFix.current = true + closeModalFn.current = fn } return { @@ -558,6 +780,15 @@ export function useOuterLineWall() { setArrow2, arrow1Ref, arrow2Ref, + angle1, + setAngle1, + angle1Ref, + angle2, + setAngle2, + angle2Ref, + outerLineDiagonalLength, + setOuterLineDiagonalLength, + outerLineDiagonalLengthRef, type, setType, handleFix, diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js new file mode 100644 index 00000000..95800dfd --- /dev/null +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -0,0 +1,89 @@ +import { useEffect, useRef } from 'react' +import { useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { LINE_TYPE } from '@/common/common' + +export function usePropertiesSetting() { + const currentLine = useRef(null) + const canvas = useRecoilValue(canvasState) + + useEffect(() => { + initLineSetting() + }, []) + + useEffect(() => { + const lines = canvas?.getObjects().filter((obj) => obj.name === 'outerLine') + lines.forEach((line) => { + line.set({ + type: line.type, + stroke: line.type === LINE_TYPE.WALLLINE.EAVES ? '#45CD7D' : line.type === LINE_TYPE.WALLLINE.GABLE ? '#3FBAE6' : '#000000', + strokeWidth: 4, + }) + }) + }, [currentLine.current]) + + const handleSetEaves = () => { + currentLine.current.set({ + stroke: '#45CD7D', + strokeWidth: 4, + attributes: { + offset: 500, + type: LINE_TYPE.WALLLINE.EAVES, + pitch: 4, + }, + }) + + nextLineSetting() + } + + const handleSetGable = () => { + currentLine.current.set({ + type: LINE_TYPE.WALLLINE.GABLE, + stroke: '#3FBAE6', + strokeWidth: 4, + attributes: { + offset: 300, + type: LINE_TYPE.WALLLINE.GABLE, + }, + }) + + nextLineSetting() + } + + const initLineSetting = () => { + currentLine.current = canvas?.getObjects().filter((obj) => obj.name === 'outerLine')[0] + + currentLine.current.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + + canvas?.renderAll() + } + + const nextLineSetting = () => { + // currentLine.current의 값은 currentLine.current의 idx 다음 값, 없을 경우는 null + currentLine.current = canvas?.getObjects().find((obj) => obj.idx === currentLine.current.idx + 1) + + if (!currentLine.current) { + canvas?.renderAll() + handleFix() + return + } + + currentLine.current = currentLine.current.set({ + stroke: '#EA10AC', + strokeWidth: 4, + }) + + canvas?.renderAll() + } + + const currentLineSetting = () => {} + + const handleRollback = () => {} + + const handleFix = () => {} + + return { handleSetEaves, handleSetGable, handleRollback, handleFix } +} diff --git a/src/hooks/useAdsorptionPoint.js b/src/hooks/useAdsorptionPoint.js index 44e2495b..49d49714 100644 --- a/src/hooks/useAdsorptionPoint.js +++ b/src/hooks/useAdsorptionPoint.js @@ -26,7 +26,7 @@ export function useAdsorptionPoint() { top: pointer.y - 3, x: pointer.x, y: pointer.y, - selectable: false, + selectable: true, name: 'adsorptionPoint', }) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 37ffdc5f..0f506fd3 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -36,6 +36,7 @@ export function useCanvas(id) { setCanvas(c) setCanvasForEvent(c) + attachDefaultEventOnCanvas() return () => { // c.dispose() @@ -45,7 +46,6 @@ export function useCanvas(id) { useEffect(() => { // canvas 사이즈가 변경되면 다시 - attachDefaultEventOnCanvas() }, [canvasSize]) useEffect(() => { @@ -91,6 +91,13 @@ export function useCanvas(id) { // settings for all canvas in the app fabric.Object.prototype.transparentCorners = false fabric.Object.prototype.id = uuidv4() + fabric.Object.prototype.selectable = true + fabric.Object.prototype.lockMovementX = true + fabric.Object.prototype.lockMovementY = true + fabric.Object.prototype.lockRotation = true + fabric.Object.prototype.lockScalingX = true + fabric.Object.prototype.lockScalingY = true + fabric.Object.prototype.cornerColor = '#2BEBC8' fabric.Object.prototype.cornerStyle = 'rect' fabric.Object.prototype.cornerStrokeColor = '#2BEBC8' diff --git a/src/hooks/useDotLineGrid.js b/src/hooks/useDotLineGrid.js index 34d82fa7..0c21c030 100644 --- a/src/hooks/useDotLineGrid.js +++ b/src/hooks/useDotLineGrid.js @@ -6,6 +6,7 @@ import { gridColorState } from '@/store/gridAtom' export function useDotLineGrid() { const canvas = useRecoilValue(canvasState) + const gridColor = useRecoilValue(gridColorState) const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 31a2cd8a..67ff8c44 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -1,24 +1,16 @@ import { useEffect, useRef } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' -import { - adsorptionPointAddModeState, - adsorptionPointModeState, - adsorptionRangeState, - canvasState, - canvasZoomState, - currentMenuState, -} from '@/store/canvasAtom' +import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom' import { fabric } from 'fabric' -import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' -import { useMouse } from '@/hooks/useMouse' import { useDotLineGrid } from '@/hooks/useDotLineGrid' import { useTempGrid } from '@/hooks/useTempGrid' export function useEvent() { const canvas = useRecoilValue(canvasState) const currentMenu = useRecoilValue(currentMenuState) - const keyboardEventListeners = useRef([]) + const documentEventListeners = useRef([]) const mouseEventListeners = useRef([]) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) @@ -30,9 +22,8 @@ export function useEvent() { if (!canvas) { return } - removeAllMouseEventListeners() removeAllDocumentEventListeners() - + removeAllMouseEventListeners() /** * wheelEvent */ @@ -193,13 +184,14 @@ export function useEvent() { } const addCanvasMouseEventListener = (eventType, handler) => { + canvas.off(eventType) canvas.on(eventType, handler) mouseEventListeners.current.push({ eventType, handler }) } const removeAllMouseEventListeners = () => { mouseEventListeners.current.forEach(({ eventType, handler }) => { - canvas.off(eventType, handler) + canvas.off(eventType) }) mouseEventListeners.current.length = 0 // 배열 초기화 } @@ -211,24 +203,36 @@ export function useEvent() { * @param handler */ const addDocumentEventListener = (eventType, element, handler) => { + removeDocumentEvent(eventType) element.addEventListener(eventType, handler) - keyboardEventListeners.current.push({ eventType, element, handler }) + documentEventListeners.current.push({ eventType, element, handler }) } /** * document에 등록되는 event 제거 */ const removeAllDocumentEventListeners = () => { - keyboardEventListeners.current.forEach(({ eventType, element, handler }) => { + documentEventListeners.current.forEach(({ eventType, element, handler }) => { element.removeEventListener(eventType, handler) }) - keyboardEventListeners.current.length = 0 // 배열 초기화 + documentEventListeners.current.length = 0 // 배열 초기화 } - const removeMouseEvent = (type, handler) => { + const removeMouseEvent = (type) => { mouseEventListeners.current = mouseEventListeners.current.filter((event) => { - if (event.type === type && event.handler === handler) { - canvas.off(type, handler) + if (event.eventType === type) { + canvas.off(type, event.handler) + return false + } + return true + }) + } + + const removeDocumentEvent = (type) => { + documentEventListeners.current = documentEventListeners.current.filter((event) => { + if (event.eventType === type) { + console.log(type) + event.element.removeEventListener(type, event.handler) return false } return true diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index e701a2ff..d42af418 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -38,6 +38,7 @@ export const useLine = () => { const removeLine = (line) => { removeLineText(line) canvas?.remove(line) + canvas?.renderAll() } const removeLineText = (line) => { From 05d2db69c376360736e920554baa8d098ab30d0c Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 30 Sep 2024 16:22:00 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outerlinesetting/PropertiesSetting.jsx | 17 ++- src/hooks/roofcover/usePropertiesSetting.js | 116 ++++++++++++------ 2 files changed, 92 insertions(+), 41 deletions(-) diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index 0120f6a4..cd2973e7 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -6,14 +6,19 @@ export default function PropertiesSetting(props) { const { getMessage } = useMessage() const { setShowPropertiesSettingModal } = props - const { handleSetEaves, handleSetGable, handleRollback, handleFix } = usePropertiesSetting() + const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting() return (

{getMessage('modal.canvas.setting.wallline.properties.setting')}

-
@@ -34,7 +39,13 @@ export default function PropertiesSetting(props) { -
diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index 95800dfd..9df385ed 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -1,27 +1,17 @@ import { useEffect, useRef } from 'react' +import { LINE_TYPE } from '@/common/common' import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' -import { LINE_TYPE } from '@/common/common' export function usePropertiesSetting() { const currentLine = useRef(null) + const currentIdx = useRef(-1) const canvas = useRecoilValue(canvasState) useEffect(() => { - initLineSetting() + selectNextLine() }, []) - useEffect(() => { - const lines = canvas?.getObjects().filter((obj) => obj.name === 'outerLine') - lines.forEach((line) => { - line.set({ - type: line.type, - stroke: line.type === LINE_TYPE.WALLLINE.EAVES ? '#45CD7D' : line.type === LINE_TYPE.WALLLINE.GABLE ? '#3FBAE6' : '#000000', - strokeWidth: 4, - }) - }) - }, [currentLine.current]) - const handleSetEaves = () => { currentLine.current.set({ stroke: '#45CD7D', @@ -32,13 +22,12 @@ export function usePropertiesSetting() { pitch: 4, }, }) - - nextLineSetting() + canvas.renderAll() + selectNextLine() } const handleSetGable = () => { currentLine.current.set({ - type: LINE_TYPE.WALLLINE.GABLE, stroke: '#3FBAE6', strokeWidth: 4, attributes: { @@ -46,44 +35,95 @@ export function usePropertiesSetting() { type: LINE_TYPE.WALLLINE.GABLE, }, }) - - nextLineSetting() + canvas.renderAll() + selectNextLine() } - const initLineSetting = () => { - currentLine.current = canvas?.getObjects().filter((obj) => obj.name === 'outerLine')[0] + const selectNextLine = () => { + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + currentIdx.current++ + + if (currentIdx.current >= lines.length) { + currentIdx.current = lines.length + currentLine.current = lines[currentIdx.current - 1] + return + } + + currentLine.current = lines[currentIdx.current] currentLine.current.set({ stroke: '#EA10AC', strokeWidth: 4, }) - canvas?.renderAll() + canvas.renderAll() } - const nextLineSetting = () => { - // currentLine.current의 값은 currentLine.current의 idx 다음 값, 없을 경우는 null - currentLine.current = canvas?.getObjects().find((obj) => obj.idx === currentLine.current.idx + 1) + const selectPrevLine = () => { + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') - if (!currentLine.current) { - canvas?.renderAll() - handleFix() + currentIdx.current-- + + if (currentIdx.current <= -1) { + currentIdx.current = -1 + selectNextLine() + return + } else { + lines.forEach((line, index) => { + if (index >= currentIdx.current) { + delete line.attributes + line.set({ + stroke: '#000000', + strokeWidth: 4, + }) + } + currentIdx.current-- + canvas.renderAll() + selectNextLine() + }) + } + } + + const handleRollback = () => { + selectPrevLine() + } + + const handleFix = () => { + if (!confirm('외벽선 속성 설정을 완료하시겠습니까?')) { + return + } + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + lines.forEach((line) => { + line.set({ + attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL }, + stroke: '#000000', + strokeWidth: 4, + }) + }) + + canvas.renderAll() + } + + const closeModal = (fn) => { + if (!confirm('외벽선 속성 설정을 종료 하시겠습니까?')) { return } - currentLine.current = currentLine.current.set({ - stroke: '#EA10AC', - strokeWidth: 4, + const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + + lines.forEach((line) => { + line.set({ + attributes: { offset: 0, type: LINE_TYPE.WALLLINE.WALL }, + stroke: '#000000', + strokeWidth: 4, + }) }) - canvas?.renderAll() + canvas.renderAll() + + fn(false) } - const currentLineSetting = () => {} - - const handleRollback = () => {} - - const handleFix = () => {} - - return { handleSetEaves, handleSetGable, handleRollback, handleFix } + return { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } }