diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx
index d8b7510c..320277fb 100644
--- a/src/components/floor-plan/CanvasMenu.jsx
+++ b/src/components/floor-plan/CanvasMenu.jsx
@@ -191,7 +191,12 @@ export default function CanvasMenu(props) {
diff --git a/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx b/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx
index 4f5c6ea7..15ccefa3 100644
--- a/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx
+++ b/src/components/floor-plan/modal/wallLineOffset/type/WallLine.jsx
@@ -1,8 +1,8 @@
import { useMessage } from '@/hooks/useMessage'
-import { useEffect, useState } from 'react'
+import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
import { useEvent } from '@/hooks/useEvent'
-export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref, radioTypeRef, currentWallLineRef }) {
+export default forwardRef(function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref, radioTypeRef, currentWallLineRef }, ref) {
const { getMessage } = useMessage()
const { addDocumentEventListener, initEvent } = useEvent()
const [type, setType] = useState(1)
@@ -10,76 +10,25 @@ export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref,
const [arrow2, setArrow2] = useState('up')
useEffect(() => {
- addDocumentEventListener('keydown', document, keyDown)
-
return () => {
initEvent()
}
}, [])
+ useImperativeHandle(ref, () => ({
+ setArrow,
+ }))
+
+ const setArrow = () => {
+ setArrow1(arrow1Ref.current)
+ setArrow2(arrow2Ref.current)
+ }
+
const onChange = (e) => {
setType(Number(e.target.value))
radioTypeRef.current = e.target.value
}
- const handleBtnClick = (direction) => {
- document.dispatchEvent(new KeyboardEvent('keydown', { key: direction }))
- }
-
- const keyDown = (e) => {
- if (currentWallLineRef.current === null) {
- alert('보조선을 먼저 선택하세요')
- return
- }
-
- const key = e.key
-
- switch (key) {
- case 'Down': // IE/Edge에서 사용되는 값
- case 'ArrowDown': {
- if (radioTypeRef.current === '1') {
- setArrow1('down')
- arrow1Ref.current = 'down'
- } else {
- setArrow2('down')
- arrow2Ref.current = 'down'
- }
-
- break
- }
- case 'Up': // IE/Edge에서 사용되는 값
- case 'ArrowUp':
- if (radioTypeRef.current === '1') {
- setArrow1('up')
- arrow1Ref.current = 'up'
- } else {
- setArrow2('up')
- arrow2Ref.current = 'up'
- }
- break
- case 'Left': // IE/Edge에서 사용되는 값
- case 'ArrowLeft':
- if (radioTypeRef.current === '1') {
- setArrow1('left')
- arrow1Ref.current = 'left'
- } else {
- setArrow2('left')
- arrow2Ref.current = 'left'
- }
- break
- case 'Right': // IE/Edge에서 사용되는 값
- case 'ArrowRight':
- if (radioTypeRef.current === '1') {
- setArrow1('right')
- arrow1Ref.current = 'right'
- } else {
- setArrow2('right')
- arrow2Ref.current = 'right'
- }
- break
- }
- }
-
return (
<>
@@ -107,10 +56,10 @@ export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref,
-
-
-
-
+
+
+
+
@@ -141,10 +90,10 @@ export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref,
-
-
-
-
+
+
+
+
@@ -155,4 +104,4 @@ export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref,
>
)
-}
+})
diff --git a/src/hooks/roofcover/useWallLineOffsetSetting.js b/src/hooks/roofcover/useWallLineOffsetSetting.js
index 6536bc80..dce62b9b 100644
--- a/src/hooks/roofcover/useWallLineOffsetSetting.js
+++ b/src/hooks/roofcover/useWallLineOffsetSetting.js
@@ -10,6 +10,7 @@ export function useWallLineOffsetSetting() {
const { showLine, addLine } = useLine()
const { getMessage } = useMessage()
const { addCanvasMouseEventListener, initEvent } = useEvent()
+ const wallLineEditRef = useRef(null)
const length1Ref = useRef(null)
const length2Ref = useRef(null)
const radioTypeRef = useRef('1')
@@ -17,6 +18,22 @@ export function useWallLineOffsetSetting() {
const arrow1Ref = useRef(null)
const arrow2Ref = useRef(null)
+ const drawLine = (point1, point2, idx) => {
+ const line = addLine([point1.x, point1.y, point2.x, point2.y], {
+ stroke: 'black',
+ strokeWidth: 4,
+ idx: idx,
+ selectable: true,
+ name: 'outerLine',
+ x1: point1.x,
+ y1: point1.y,
+ x2: point2.x,
+ y2: point2.y,
+ })
+
+ line.attributes = { ...currentWallLineRef.current.attributes }
+ }
+
const TYPES = {
WALL_LINE_EDIT: 'wallLineEdit',
OFFSET: 'offset',
@@ -36,37 +53,114 @@ export function useWallLineOffsetSetting() {
showLine(outerLine)
})
- const roofs = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
-
- roofs.forEach((roof) => {
- roof.innerLines.forEach((innerLine) => {
- canvas.remove(innerLine)
- })
- canvas.remove(roof)
+ //outerLine과 그 text만 남겨둔다.
+ const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine')
+ exceptObjs.forEach((obj) => {
+ canvas.remove(obj)
})
- const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
- wallLines.forEach((wallLine) => {
- canvas.remove(wallLine)
- })
+ canvas.setActiveObject(outerLines[0])
+ currentWallLineRef.current = outerLines[0]
+ addCircleByLine(currentWallLineRef.current)
addCanvasMouseEventListener('mouse:down', mouseDown)
return () => {
+ removeOuterLineEditCircle()
canvas.discardActiveObject()
initEvent()
}
}, [])
+ useEffect(() => {
+ removeOuterLineEditCircle()
+ addCanvasMouseEventListener('mouse:down', mouseDown)
+ if (type === TYPES.WALL_LINE_EDIT) {
+ addCircleByLine(currentWallLineRef.current)
+ }
+ }, [type])
+
+ const removeOuterLineEditCircle = () => {
+ canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'outerLineEditCircleStart' || obj.name === 'outerLineEditCircleEnd'))
+ }
+
const mouseDown = (e) => {
+ removeOuterLineEditCircle()
if (!e.target || (e.target && e.target.name !== 'outerLine')) {
+ currentWallLineRef.current = null
return
}
currentWallLineRef.current = e.target
+ if (type === TYPES.WALL_LINE_EDIT) {
+ addCircleByLine(currentWallLineRef.current)
+ }
+ }
+
+ const addCircleByLine = (line) => {
+ const direction = currentWallLineRef.current?.direction
+ let startPoint
+ let endPoint
+ let circle1, circle2
+
+ if (direction === 'top' || direction === 'bottom') {
+ // y1, y2중에 더 작은 값이 startPoint, 더 큰 값이 endPoint
+ if (line.y1 > line.y2) {
+ startPoint = { x: line.x2, y: line.y2 }
+ endPoint = { x: line.x1, y: line.y1 }
+ } else {
+ startPoint = { x: line.x1, y: line.y1 }
+ endPoint = { x: line.x2, y: line.y2 }
+ }
+ arrow1Ref.current = 'down'
+ arrow2Ref.current = 'up'
+ } else {
+ // x1, x2중에 더 작은 값이 startPoint, 더 큰 값이 endPoint
+ if (line.x1 > line.x2) {
+ startPoint = { x: line.x2, y: line.y2 }
+ endPoint = { x: line.x1, y: line.y1 }
+ } else {
+ startPoint = { x: line.x1, y: line.y1 }
+ endPoint = { x: line.x2, y: line.y2 }
+ }
+ arrow1Ref.current = 'right'
+ arrow2Ref.current = 'left'
+ }
+
+ circle1 = new fabric.Circle({
+ radius: 10,
+ fill: 'red',
+ top: startPoint.y - 10,
+ left: startPoint.x - 10,
+ name: 'outerLineEditCircleStart',
+ hasControls: false,
+ hasBorders: false,
+ lockMovementX: true,
+ lockMovementY: true,
+ })
+
+ circle2 = new fabric.Circle({
+ radius: 10,
+ fill: 'blue',
+ top: endPoint.y - 10,
+ left: endPoint.x - 10,
+ name: 'outerLineEditCircleEnd',
+ hasControls: false,
+ hasBorders: false,
+ lockMovementX: true,
+ lockMovementY: true,
+ })
+
+ wallLineEditRef.current.setArrow()
+ canvas.add(circle1)
+ canvas.add(circle2)
}
const handleSave = () => {
+ if (currentWallLineRef.current === null) {
+ alert('보조선을 먼저 선택하세요')
+ return
+ }
switch (type) {
case TYPES.WALL_LINE_EDIT:
handleWallLineEditSave()
@@ -78,19 +172,49 @@ export function useWallLineOffsetSetting() {
}
const handleWallLineEditSave = () => {
- const direction = currentWallLineRef.current.direction
- let canDirections = direction === 'left' || direction === 'right' ? ['up', 'down'] : ['left', 'right']
- if (radioTypeRef === 1) {
- if (!canDirections.includes(arrow1Ref.current)) {
- alert('방향을 다시 선택하세요')
- return
+ const startPoint = canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'outerLineEditCircleStart')
+ .map((obj) => {
+ return {
+ x: obj.left + obj.radius,
+ y: obj.top + obj.radius,
+ }
+ })[0]
+ const endPoint = canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'outerLineEditCircleEnd')
+ .map((obj) => {
+ return {
+ x: obj.left + obj.radius,
+ y: obj.top + obj.radius,
+ }
+ })[0]
+ const length = Number(length1Ref.current.value) / 10
+ let line1, line2
+ if (radioTypeRef.current === '1') {
+ // 1지점 선택시 방향은 down, right만 가능
+ if (arrow1Ref.current === 'down') {
+ drawLine({ x: startPoint.x, y: startPoint.y }, { x: startPoint.x, y: startPoint.y + length }, currentWallLineRef.current.idx)
+ drawLine({ x: startPoint.x, y: startPoint.y + length }, { x: endPoint.x, y: endPoint.y }, currentWallLineRef.current.idx)
+ } else {
+ drawLine({ x: startPoint.x, y: startPoint.y }, { x: startPoint.x + length, y: startPoint.y }, currentWallLineRef.current.idx)
+ drawLine({ x: startPoint.x + length, y: startPoint.y }, { x: endPoint.x, y: endPoint.y }, currentWallLineRef.current.idx)
}
} else {
- if (!canDirections.includes(arrow2Ref.current)) {
- alert('방향을 다시 선택하세요')
- return
+ // 2지점일 경우 방향은 up, left만 가능
+ if (arrow2Ref.current === 'up') {
+ drawLine({ x: endPoint.x, y: endPoint.y }, { x: endPoint.x, y: endPoint.y - length }, currentWallLineRef.current.idx)
+ drawLine({ x: endPoint.x, y: endPoint.y - length }, { x: startPoint.x, y: startPoint.y }, currentWallLineRef.current.idx)
+ } else {
+ drawLine({ x: endPoint.x, y: endPoint.y }, { x: endPoint.x - length, y: endPoint.y }, currentWallLineRef.current.idx)
+ drawLine({ x: endPoint.x - length, y: endPoint.y }, { x: startPoint.x, y: startPoint.y }, currentWallLineRef.current.idx)
}
}
+ removeOuterLineEditCircle()
+ canvas.remove(currentWallLineRef.current)
+ currentWallLineRef.current = null
+ canvas.renderAll()
}
const handleOffsetSave = () => {
@@ -103,26 +227,100 @@ export function useWallLineOffsetSetting() {
}
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
+
const idx = currentWallLineRef.current.idx
- const prevLine = outerLines.find((line) => (line.idx === idx - 1 < 0 ? outerLines.length - 1 : idx - 1))
+ const prevIdx = idx - 1 <= 0 ? outerLines.length : idx - 1
+ const nextIdx = idx + 1 > outerLines.length ? 1 : idx + 1
+
const currentLine = currentWallLineRef.current
- const nextLine = outerLines.find((line) => (line.idx === idx + 1 > outerLines.length - 1 ? 0 : idx + 1))
+ const prevLine = outerLines.find((line) => line.idx === prevIdx)
+ const nextLine = outerLines.find((line) => line.idx === nextIdx)
+
+ const length = length1Ref.current.value / 10
+
switch (arrow1Ref.current) {
case 'up': {
- console.log(prevLine, currentLine, nextLine)
+ const currentLineY = Math.floor(Math.max(currentLine.y1, currentLine.y2))
+ currentLine.set({ y1: currentLineY - length, y2: currentLineY - length })
+
+ if (Math.abs(currentLineY - prevLine.y1) < 2) {
+ prevLine.set({ y1: currentLineY - length })
+ } else {
+ prevLine.set({ y2: currentLineY - length })
+ }
+ if (Math.abs(currentLineY - nextLine.y1) < 2) {
+ nextLine.set({ y1: currentLineY - length })
+ } else {
+ nextLine.set({ y2: currentLineY - length })
+ }
+
break
}
case 'down': {
+ const currentLineY = Math.floor(Math.max(currentLine.y1, currentLine.y2))
+ currentLine.set({ y1: currentLineY + length, y2: currentLineY + length })
+
+ if (Math.abs(currentLineY - prevLine.y1) < 2) {
+ prevLine.set({ y1: currentLineY + length })
+ } else {
+ prevLine.set({ y2: currentLineY + length })
+ }
+ if (Math.abs(currentLineY - nextLine.y1) < 2) {
+ nextLine.set({ y1: currentLineY + length })
+ } else {
+ nextLine.set({ y2: currentLineY + length })
+ }
break
}
case 'left': {
+ const currentLineX = Math.floor(Math.max(currentLine.x1, currentLine.x2))
+ currentLine.set({ x1: currentLineX - length, x2: currentLineX - length })
+
+ if (Math.abs(currentLineX - prevLine.x1) < 2) {
+ prevLine.set({ x1: currentLineX - length })
+ } else {
+ prevLine.set({ x2: currentLineX - length })
+ }
+ if (Math.abs(currentLineX - nextLine.x1) < 2) {
+ nextLine.set({ x1: currentLineX - length })
+ } else {
+ nextLine.set({ x2: currentLineX - length })
+ }
break
}
case 'right': {
+ const currentLineX = Math.floor(Math.max(currentLine.x1, currentLine.x2))
+ currentLine.set({ x1: currentLineX + length, x2: currentLineX + length })
+
+ if (Math.abs(currentLineX - prevLine.x1) < 2) {
+ prevLine.set({ x1: currentLineX + length })
+ } else {
+ prevLine.set({ x2: currentLineX + length })
+ }
+ if (Math.abs(currentLineX - nextLine.x1) < 2) {
+ nextLine.set({ x1: currentLineX + length })
+ } else {
+ nextLine.set({ x2: currentLineX + length })
+ }
+
break
}
}
+ canvas.renderAll()
}
- return { type, setType, buttonMenu, TYPES, length1Ref, length2Ref, radioTypeRef, currentWallLineRef, arrow1Ref, arrow2Ref, handleSave }
+ return {
+ type,
+ setType,
+ buttonMenu,
+ TYPES,
+ length1Ref,
+ length2Ref,
+ radioTypeRef,
+ currentWallLineRef,
+ arrow1Ref,
+ arrow2Ref,
+ handleSave,
+ wallLineEditRef,
+ }
}