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() {
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 (
<>
{getMessage('modal.cover.outline.arrow')}
-
-
-
-
+
+
+
+
@@ -40,16 +108,48 @@ export default function Diagonal() {
{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.arrow')}
-
-
-
-
+
+
+
+
@@ -38,26 +123,80 @@ export default function DoublePitch() {
{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.js
deleted file mode 100644
index c4950666..00000000
--- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import WithDraggable from '@/components/common/draggable/WithDraggable'
-import { useMessage } from '@/hooks/useMessage'
-
-export default function PropertiesSetting(props) {
- const { getMessage } = useMessage()
- const { setShowPropertiesSettingModal } = props
-
- return (
-
-
-
-
{getMessage('modal.canvas.setting.wallline.properties.setting')}
-
-
-
-
{getMessage('modal.canvas.setting.wallline.properties.setting.info')}
-
-
{getMessage('setting')}
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx
new file mode 100644
index 00000000..cd2973e7
--- /dev/null
+++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx
@@ -0,0 +1,56 @@
+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, closeModal } = usePropertiesSetting()
+
+ return (
+
+
+
+
{getMessage('modal.canvas.setting.wallline.properties.setting')}
+
+
+
+
{getMessage('modal.canvas.setting.wallline.properties.setting.info')}
+
+
{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.arrow')}
-
-
-
-
+
+
+
+
@@ -26,17 +65,53 @@ export default function RightAngle() {
{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..9df385ed
--- /dev/null
+++ b/src/hooks/roofcover/usePropertiesSetting.js
@@ -0,0 +1,129 @@
+import { useEffect, useRef } from 'react'
+import { LINE_TYPE } from '@/common/common'
+import { useRecoilValue } from 'recoil'
+import { canvasState } from '@/store/canvasAtom'
+
+export function usePropertiesSetting() {
+ const currentLine = useRef(null)
+ const currentIdx = useRef(-1)
+ const canvas = useRecoilValue(canvasState)
+
+ useEffect(() => {
+ selectNextLine()
+ }, [])
+
+ const handleSetEaves = () => {
+ currentLine.current.set({
+ stroke: '#45CD7D',
+ strokeWidth: 4,
+ attributes: {
+ offset: 500,
+ type: LINE_TYPE.WALLLINE.EAVES,
+ pitch: 4,
+ },
+ })
+ canvas.renderAll()
+ selectNextLine()
+ }
+
+ const handleSetGable = () => {
+ currentLine.current.set({
+ stroke: '#3FBAE6',
+ strokeWidth: 4,
+ attributes: {
+ offset: 300,
+ type: LINE_TYPE.WALLLINE.GABLE,
+ },
+ })
+ canvas.renderAll()
+ selectNextLine()
+ }
+
+ 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()
+ }
+
+ const selectPrevLine = () => {
+ const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
+
+ 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
+ }
+
+ 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()
+
+ fn(false)
+ }
+
+ return { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal }
+}
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) => {