From 8834f975a80ac7d556e139c762098b64a48ee94a Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 19 Sep 2024 10:55:32 +0900 Subject: [PATCH] =?UTF-8?q?=EC=99=B8=EB=B2=BD=EC=84=A0=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasMenu.jsx | 6 +- .../modal/outerlinesetting/OuterLineWall.jsx | 61 +++++++++++++++++-- src/hooks/useEvent.js | 6 +- src/hooks/useLine.js | 15 ++++- src/hooks/usePolygon.js | 20 +++++- src/store/canvasAtom.js | 11 ++++ 6 files changed, 103 insertions(+), 16 deletions(-) diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 477cdfde..656bae3e 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -6,11 +6,13 @@ import { useMessage } from '@/hooks/useMessage' import { post } from '@/lib/Axios' import { useRecoilState } from 'recoil' import { settingModalFirstOptionsState } from '@/store/settingAtom' +import { verticalHorizontalModeState } from '@/store/canvasAtom' export default function CanvasMenu(props) { const [objectNo] = useState('test123240912001') const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props const [menuNumber, setMenuNumber] = useState(null) + const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState) const [vertical, setVertical] = useState(true) const [type, setType] = useState('') const { getMessage } = useMessage() @@ -135,9 +137,9 @@ export default function CanvasMenu(props) { {menuNumber !== 4 && ( -
+
{getMessage('plan.mode.vertical.horizontal')} - +
)}
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx index c8a61e11..f318331e 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx @@ -5,7 +5,7 @@ import WithDraggable from '@/components/common/draggable/withDraggable' import { useRecoilState, useRecoilValue } from 'recoil' import { useMessage } from '@/hooks/useMessage' import { useEvent } from '@/hooks/useEvent' -import { canvasState } from '@/store/canvasAtom' +import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom' import { OUTER_LINE_TYPE, outerLineArrow1State, @@ -17,12 +17,15 @@ import { } from '@/store/outerLineAtom' import { QLine } from '@/components/fabric/QLine' import { useLine } from '@/hooks/useLine' +import { distanceBetweenPoints } from '@/util/canvas-util' export default function OuterLineWall(props) { const { setShowOutlineModal } = props const { getMessage } = useMessage() - const { addCanvasMouseEventListener, addDocumentEventListener, removeAllDocumentEventListeners } = useEvent() + const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent() const { addLineText, removeLineText } = useLine() + const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) + const length1Ref = useRef(null) const length2Ref = useRef(null) const [length1, setLength1] = useRecoilState(outerLineLength1State) @@ -37,8 +40,9 @@ export default function OuterLineWall(props) { const canvas = useRecoilValue(canvasState) useEffect(() => { + removeAllMouseEventListeners() addCanvasMouseEventListener('mouse:down', mouseDown) - }, []) + }, [verticalHorizontalMode, points]) useEffect(() => { arrow1Ref.current = arrow1 @@ -64,8 +68,44 @@ export default function OuterLineWall(props) { const mouseDown = (e) => { const pointer = canvas.getPointer(e.e) + if (points.length === 0) { + setPoints((prev) => [...prev, pointer]) + } else { + const lastPoint = points[points.length - 1] + let newPoint = { x: pointer.x, y: pointer.y } + const length = distanceBetweenPoints(lastPoint, newPoint) + if (verticalHorizontalMode) { + const vector = { + x: pointer.x - points[points.length - 1].x, + y: pointer.y - points[points.length - 1].y, + } + const slope = Math.abs(vector.y / vector.x) // 기울기 계산 - setPoints((prev) => [...prev, pointer]) + let scaledVector + if (slope >= 1) { + // 기울기가 1 이상이면 x축 방향으로 그림 + scaledVector = { + x: 0, + y: vector.y >= 0 ? Number(length) : -Number(length), + } + } else { + // 기울기가 1 미만이면 y축 방향으로 그림 + scaledVector = { + x: vector.x >= 0 ? Number(length) : -Number(length), + y: 0, + } + } + + const verticalLength = scaledVector.y + const horizontalLength = scaledVector.x + + newPoint = { + x: lastPoint.x + horizontalLength, + y: lastPoint.y + verticalLength, + } + } + setPoints((prev) => [...prev, newPoint]) + } } useEffect(() => { @@ -77,6 +117,11 @@ export default function OuterLineWall(props) { removeLineText(obj) }) canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) + + // point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록 + removeAllDocumentEventListeners() + addDocumentEventListener('keydown', document, keydown[type]) + if (points.length === 0) { return } @@ -190,6 +235,9 @@ export default function OuterLineWall(props) { const keydown = { outerLine: (e) => { + if (points.length === 0) { + return + } const key = e.key if (!length1Ref.current) { @@ -245,11 +293,12 @@ export default function OuterLineWall(props) { } }, rightAngle: (e) => { + if (points.length === 0) { + return + } const key = e.key const activeElem = document.activeElement - const length1Num = Number(length1Ref.current.value) / 10 - const length2Num = Number(length2Ref.current.value) / 10 switch (key) { case 'Down': // IE/Edge에서 사용되는 값 diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 715a27b0..ab17ccaa 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -13,11 +13,6 @@ export function useEvent() { if (!canvas) { return } - Object.keys(canvas.__eventListeners).forEach((key) => { - if (key.indexOf('mouse') > -1) { - canvas.off(key) - } - }) removeAllMouseEventListeners() removeAllDocumentEventListeners() addDefaultEvent() @@ -112,6 +107,7 @@ export function useEvent() { return { addDocumentEventListener, addCanvasMouseEventListener, + removeAllMouseEventListeners, removeAllDocumentEventListeners, } } diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index 81ebd1db..3d2f6f19 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -1,9 +1,20 @@ import { useRecoilValue } from 'recoil' -import { canvasState, fontSizeState } from '@/store/canvasAtom' +import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' export const useLine = () => { const canvas = useRecoilValue(canvasState) const fontSize = useRecoilValue(fontSizeState) + const fontFamily = useRecoilValue(fontFamilyState) + + const addLine = (points = [], options) => { + const line = new fabric.Line(points, { + ...options, + selectable: options.selectable ?? false, + }) + + canvas?.add(line) + return line + } const addLineText = (line) => { removeLineText(line) @@ -14,9 +25,11 @@ export const useLine = () => { parent: line, name: 'lengthTxt', fontSize: fontSize, + fontFamily: fontFamily, }) canvas?.add(text) + return text } const removeLineText = (line) => { diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 72354443..60db96b9 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1,8 +1,24 @@ -import { canvasState } from '@/store/canvasAtom' +import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' export const usePolygon = () => { const canvas = useRecoilValue(canvasState) + const fontSize = useRecoilValue(fontSizeState) + const fontFamily = useRecoilValue(fontFamilyState) - return {} + const addPolygon = (points, options) => { + const polygon = new fabric.Polygon(points, { + ...options, + selectable: options.selectable ?? false, + }) + + canvas?.add(polygon) + } + + const addPolygonByLines = (lines) => {} + + return { + addPolygon, + addPolygonByLines, + } } diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 48dced68..ec720275 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -22,6 +22,11 @@ export const guideModeLineState = atom({ default: false, }) +export const fontFamilyState = atom({ + key: 'fontFamilyState', + default: 'Noto Sans KR', +}) + export const fontSizeState = atom({ key: 'fontSizeState', default: 16, @@ -185,3 +190,9 @@ export const currentMenuState = atom({ key: 'currentMenu', default: MENU.INITIAL_CANVAS_SETTING, }) + +// 수직 수평 모드 +export const verticalHorizontalModeState = atom({ + key: 'verticalHorizontalMode', + default: true, +})