From 8fe2960f92a9c0b9a9c35b77f2a37afc40ede2f3 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 23 Aug 2024 16:38:16 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B7=B8=EB=A6=AC=EB=93=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=9B=84=20=EC=97=90=EB=94=94=ED=8C=85=20=EB=AA=A8?= =?UTF-8?q?=EB=93=9C=20=EB=B3=80=EA=B2=BD=20=EC=8B=9C=20=EA=B0=80=EA=B9=8C?= =?UTF-8?q?=EC=9A=B4=20line=EC=97=90=20=EB=B6=99=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 4 +- src/hooks/useMode.js | 126 +++++++++++++++++++++++---------------- src/util/canvas-util.js | 32 +++++++++- 3 files changed, 110 insertions(+), 52 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 13cecc35..7467a634 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -26,12 +26,14 @@ import ThumbnailList from './ui/ThumbnailLIst' import QContextMenu from './common/context-menu/QContextMenu' import { modalContent, modalState } from '@/store/modalAtom' import SettingsModal from './SettingsModal' -import { get } from '@/lib/Axios' +import { useAxios } from '@/hooks/useAxios' export default function Roof2(props) { const { name, userId, email, isLoggedIn } = props const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas') + const { get } = useAxios() + const canvasRef = useRef(null) //canvas 기본 사이즈 diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 936579b2..ffca9f48 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4,6 +4,8 @@ import { distanceBetweenPoints, findTopTwoIndexesByDistance, getCenterPoint, + getClosestHorizontalLine, + getClosestVerticalLine, getDirection, getStartIndex, rearrangeArray, @@ -42,7 +44,6 @@ export function useMode() { const [canvas, setCanvas] = useState(null) const [zoom, setZoom] = useState(100) const [fontSize] = useRecoilState(fontSizeState) - const [shape, setShape] = useState(0) const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray) const [roof, setRoof] = useRecoilState(roofState) const [wall, setWall] = useRecoilState(wallState) @@ -65,7 +66,7 @@ export function useMode() { const compass = useRecoilValue(compassState) const [isCellCenter, setIsCellCenter] = useState(false) - const guideLine = useRecoilValue(guideLineState) + const guideLineInfo = useRecoilValue(guideLineState) useEffect(() => { // 이벤트 리스너 추가 @@ -107,7 +108,27 @@ export function useMode() { }, [mode, isGuidePointMode]) const drawMouseLines = (e) => { - console.log('guideLine', guideLine) + let isGuideLineMode = false, + isGuideDotMode = false + let guideDotLength, guideLineLength, horizontalLineArray, verticalLineArray + + if (isObjectNotEmpty(guideLineInfo)) { + const guideLineState = guideLineInfo.filter((item) => item.guideMode === 'guideLine') + const guideDotState = guideLineInfo.filter((item) => item.guideMode === 'guideDot') + + isGuideLineMode = guideLineState.length > 0 + isGuideDotMode = guideDotState.length > 0 + + if (isGuideDotMode) { + guideDotLength = Number(guideDotState[0].moduleLength) + } + + if (isGuideLineMode) { + horizontalLineArray = [...guideLineState[0].horizontalLineArray] + verticalLineArray = [...guideLineState[0].verticalLineArray] + guideLineLength = Number(guideLineState[0].moduleLength) + } + } // 현재 마우스 포인터의 위치를 가져옵니다. const pointer = canvas?.getPointer(e.e) @@ -115,21 +136,56 @@ export function useMode() { // 기존에 그려진 가이드라인을 제거합니다. removeMouseLines() - if (canvas?.getActiveObject()) { - return - } - let newX, newY - if (isGuidePointMode && mode === Mode.EDIT) { - newX = Math.round(pointer.x / 200) * 200 - newY = Math.round(pointer.y / 200) * 200 - } else { - newX = pointer.x - newY = pointer.y + let newX = pointer.x + let newY = pointer.y + + if (isGuideLineMode && isGuideDotMode && mode === Mode.EDIT) { + } else if (isGuideDotMode && mode === Mode.EDIT) { + const x = pointer.x - guideDotLength * Math.floor(pointer.x / guideDotLength) + const y = pointer.y - guideDotLength * Math.floor(pointer.y / guideDotLength) + + const xRate = x / guideDotLength + const yRate = y / guideDotLength + const isAttachX = xRate >= 0.4 && xRate <= 0.7 + const isAttachY = yRate >= 0.4 && yRate <= 0.7 + + if (isAttachX && isAttachY) { + newX = Math.floor(pointer.x / guideDotLength) * guideDotLength + guideDotLength / 2 + newY = Math.floor(pointer.y / guideDotLength) * guideDotLength + guideDotLength / 2 + } + } else if (isGuideLineMode && mode === Mode.EDIT) { + const closestHorizontalLine = getClosestHorizontalLine(pointer, horizontalLineArray) + const closetVerticalLine = getClosestVerticalLine(pointer, verticalLineArray) + const xDiff = Math.abs(pointer.x - closetVerticalLine.x1) + const yDiff = Math.abs(pointer.y - closestHorizontalLine.y1) + + const x = pointer.x - guideLineLength * Math.floor(pointer.x / guideLineLength) + const y = pointer.y - guideLineLength * Math.floor(pointer.y / guideLineLength) + + const xRate = x / guideLineLength + const yRate = y / guideLineLength + const isAttachX = xRate >= 0.4 && xRate <= 0.7 + const isAttachY = yRate >= 0.4 && yRate <= 0.7 + + if (isAttachX && isAttachY) { + newX = Math.floor(pointer.x / guideLineLength) * guideLineLength + guideLineLength / 2 + newY = Math.floor(pointer.y / guideLineLength) * guideLineLength + guideLineLength / 2 + } else { + if (Math.min(xDiff, yDiff) <= 20) { + if (xDiff < yDiff) { + newX = closetVerticalLine.x1 + newY = pointer.y + } else { + newX = pointer.x + newY = closestHorizontalLine.y1 + } + } + } } // 가로선을 그립니다. const horizontalLine = new fabric.Line([0, newY, canvasSize.horizontal, newY], { - stroke: 'black', + stroke: 'red', strokeWidth: 1, selectable: false, name: 'mouseLine', @@ -137,7 +193,7 @@ export function useMode() { // 세로선을 그립니다. const verticalLine = new fabric.Line([newX, 0, newX, canvasSize.vertical], { - stroke: 'black', + stroke: 'red', strokeWidth: 1, selectable: false, name: 'mouseLine', @@ -762,10 +818,8 @@ export function useMode() { points.current = [] historyPoints.current = [] - // handleOuterlines() const wall = makePolygon(null, sort) wall.set({ name: 'wall' }) - console.log('wall', wall) return wall } @@ -804,33 +858,7 @@ export function useMode() { const makePolygon = (otherLines, sort = true) => { // 캔버스에서 모든 라인 객체를 찾습니다. const lines = otherLines || historyLines.current - - if (!otherLines) { - //외각선 기준 - const topIndex = findTopTwoIndexesByDistance(sortedArray) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨 - - //일단 배열 6개 짜리 기준의 선 번호 - if (topIndex[0] === 4) { - if (topIndex[1] === 5) { - //1번 - setShape(1) - } - } else if (topIndex[0] === 1) { - //4번 - if (topIndex[1] === 2) { - setShape(4) - } - } else if (topIndex[0] === 0) { - if (topIndex[1] === 1) { - //2번 - setShape(2) - } else if (topIndex[1] === 5) { - setShape(3) - } - } - - historyLines.current = [] - } + historyLines.current = [] // 각 라인의 시작점과 끝점을 사용하여 다각형의 점 배열을 생성합니다. const points = lines.map((line) => ({ x: line.x1, y: line.y1 })) @@ -858,12 +886,10 @@ export function useMode() { canvas.add(polygon) // 캔버스를 다시 그립니다. - if (!otherLines) { - // polygon.fillCell() - canvas?.renderAll() - // polygon.setViewLengthText(false) - setMode(Mode.DEFAULT) - } + // polygon.fillCell() + canvas?.renderAll() + // polygon.setViewLengthText(false) + setMode(Mode.DEFAULT) return polygon } diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 7374c024..268370c1 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -38,7 +38,7 @@ export function actionHandler(eventData, transform, x, y) { // define a function that can keep the polygon in the same position when we change its width/height/top/left export function anchorWrapper(anchorIndex, fn) { - return function(eventData, transform, x, y) { + return function (eventData, transform, x, y) { let fabricObject = transform.target let originX = fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x let originY = fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y @@ -675,3 +675,33 @@ export function findClosestPointWithDifferentXY(targetPoint, points) { return closestPoint } + +export const getClosestHorizontalLine = (pointer, horizontalLineArray) => { + let closestLine = null + let minDistance = Infinity + + horizontalLineArray.forEach((line) => { + const distance = Math.abs(line.y1 - pointer.y) // Assuming horizontal lines have the same y1 and y2 + if (distance < minDistance) { + minDistance = distance + closestLine = line + } + }) + + return closestLine +} + +export const getClosestVerticalLine = (pointer, verticalLineArray) => { + let closestLine = null + let minDistance = Infinity + + verticalLineArray.forEach((line) => { + const distance = Math.abs(line.x1 - pointer.x) // Assuming horizontal lines have the same y1 and y2 + if (distance < minDistance) { + minDistance = distance + closestLine = line + } + }) + + return closestLine +}