From 6a8579c56d45a62db0c482b0b2cc325ae5e30bc5 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 30 Oct 2024 11:22:56 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B9=98=EC=88=98=EC=84=A0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 3 + src/components/floor-plan/CanvasFrame.jsx | 2 +- src/hooks/common/useCanvasConfigInitialize.js | 44 ++++ src/hooks/common/useCommonUtils.js | 234 +++++++++--------- src/hooks/usePlan.js | 27 ++ 5 files changed, 186 insertions(+), 124 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index c8dc5383..e1e9bb2c 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -153,6 +153,9 @@ export const SAVE_KEY = [ 'pitch', 'uuid', 'originText', + 'groupYn', + 'groupName', + 'lineDirection', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index 4c078141..7c9ece42 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -44,7 +44,7 @@ export default function CanvasFrame() { useEffect(() => { if (modifiedPlanFlag && selectedPlan?.id) { - checkCanvasObjectEvent(selectedPlan.id) + // checkCanvasObjectEvent(selectedPlan.id) } }, [modifiedPlanFlag]) diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js index f49b4cb9..4df81090 100644 --- a/src/hooks/common/useCanvasConfigInitialize.js +++ b/src/hooks/common/useCanvasConfigInitialize.js @@ -59,6 +59,7 @@ export function useCanvasConfigInitialize() { const canvasLoadInit = () => { roofInit() //화면표시 초기화 + groupInit() } const gridInit = () => { @@ -94,5 +95,48 @@ export function useCanvasConfigInitialize() { }) } + const groupInit = () => { + const groups = canvas.getObjects().filter((obj) => obj.groupYn) + const groupIds = [] + + groups.forEach((group) => { + if (!groupIds.includes(group.id)) { + groupIds.push(group.id) + } + }) + + groupIds.forEach((id) => { + const groupObjects = canvas.getObjects().filter((obj) => obj.id === id && obj.type !== 'text') + const objectsName = canvas.getObjects().filter((obj) => obj.id === id && obj.type !== 'text')[0].groupName + const lineDirection = canvas.getObjects().filter((obj) => obj.id === id && obj.name === 'centerLine')[0].lineDirection + const text = canvas.getObjects().filter((obj) => obj.id === id && obj.type === 'text')[0] + + let objectArray = [] + + if (groupObjects) { + groupObjects.forEach((obj) => { + objectArray.push(obj) + }) + } + objectArray.push(text) + + objectArray.forEach((obj) => { + canvas?.remove(obj) + }) + + const group = new fabric.Group(objectArray, { + groupId: id, + name: objectsName, + selectable: true, + lockMovementX: true, + lockMovementY: true, + originX: 'center', + originY: 'center', + lineDirection: lineDirection, + }) + canvas.add(group) + }) + } + return { canvasLoadInit, gridInit } } diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js index 5f02900d..ca9b8def 100644 --- a/src/hooks/common/useCommonUtils.js +++ b/src/hooks/common/useCommonUtils.js @@ -10,7 +10,7 @@ import { v4 as uuidv4 } from 'uuid' import { usePopup } from '@/hooks/usePopup' import Distance from '@/components/floor-plan/modal/distance/Distance' import { commonUtilsState } from '@/store/commonUtilsAtom' -import { point } from '@turf/turf' +import { center, point } from '@turf/turf' export function useCommonUtils() { const canvas = useRecoilValue(canvasState) @@ -224,10 +224,14 @@ export function useCommonUtils() { }) // 두 포인트 간에 직선을 그림 (중심을 기준으로) - const line = new fabric.Line([p1CenterX, p1CenterY, p2CenterX, p2CenterY], { ...lineOptions, name: 'centerLine', id: uuid }) - canvas.add(line) + const line = new fabric.Line([p1CenterX, p1CenterY, p2CenterX, p2CenterY], { + ...lineOptions, + name: 'centerLine', + id: uuid, + }) + // canvas.add(line) - // groupObjects.push(line) + groupObjects.push(line) const distance = getDistance(p1CenterX, p1CenterY, p2CenterX, p2CenterY) const lineDirection = checkLineOrientation(line) @@ -235,49 +239,22 @@ export function useCommonUtils() { const extendListArray = createDimensionExtendLine(line, lineDirection) extendListArray.forEach((line) => { - const extendLine = new fabric.Line(line, { ...lineOptions, name: 'extendLine', id: uuid }) + const extendLine = new fabric.Line(line, { + ...lineOptions, + name: 'extendLine', + id: uuid, + }) // canvas.add(extendLine) groupObjects.push(extendLine) }) - // // 첫 번째 포인트에 화살표 추가 좌측 -> 우측으로 그릴때 - // let paddingX = lineDirection === 'horizontal' ? p1CenterX + 7.5 : p1CenterX + 0.5 - // let paddingX2 = lineDirection === 'horizontal' ? p2CenterX - 7.5 : p2CenterX + 0.5 - // let paddingY = lineDirection === 'horizontal' ? p1CenterY + 0.5 : p1CenterY + 8 - // let paddingY2 = lineDirection === 'horizontal' ? p2CenterY + 0.5 : p2CenterY - 8 - // let angle1 = lineDirection === 'horizontal' ? -90 : 0 - // let angle2 = lineDirection === 'horizontal' ? 90 : 180 - - // // 우측 -> 좌측으로 그릴땐 반대 - // if (paddingX > paddingX2 || paddingY > paddingY2) { - // paddingX = lineDirection === 'horizontal' ? p1CenterX - 7.5 : p1CenterX + 0.5 - // paddingX2 = lineDirection === 'horizontal' ? p2CenterX + 7.5 : p2CenterX + 0.5 - // paddingY = lineDirection === 'horizontal' ? p1CenterY + 0.5 : p1CenterY - 7.5 - // paddingY2 = lineDirection === 'horizontal' ? p2CenterY + 0.5 : p2CenterY + 7.5 - // angle1 = lineDirection === 'horizontal' ? 90 : 180 - // angle2 = lineDirection === 'horizontal' ? 270 : 0 - // } - const dimensionPosition = calcDimensionPosition(lineDirection, p1CenterX, p1CenterY, p2CenterX, p2CenterY) - const arrow1 = createDimensionArrow(dimensionPosition.paddingX, dimensionPosition.paddingY, dimensionPosition.angle1, uuid) // 반대 방향 화살표 const arrow2 = createDimensionArrow(dimensionPosition.paddingX2, dimensionPosition.paddingY2, dimensionPosition.angle2, uuid) // 정방향 화살표 // canvas.add(arrow1) // canvas.add(arrow2) - groupObjects.push(arrow1) - groupObjects.push(arrow2) - - const group = new fabric.Group(groupObjects, { - name: 'dimensionLine', - selectable: true, - originX: 'center', - originY: 'center', - lineDirection: lineDirection, - id: uuid, - }) - - canvas.add(group) + groupObjects.push(arrow1, arrow2) distanceText = new fabric.Text(`${distance * 10} `, { left: (p1CenterX + p2CenterX) / 2 + (lineDirection === 'horizontal' ? 0 : -15), @@ -296,7 +273,19 @@ export function useCommonUtils() { // lockMovementX: false, // lockMovementY: false, }) - canvas.add(distanceText) + // canvas.add(distanceText) + groupObjects.push(distanceText) + + const group = new fabric.Group(groupObjects, { + name: 'dimensionLine', + selectable: true, + originX: 'center', + originY: 'center', + lineDirection: lineDirection, + groupId: uuid, + }) + + canvas.add(group) // groupObjects.push(distanceText) @@ -544,16 +533,19 @@ export function useCommonUtils() { lockMovementY: false, }) + const originLeft = obj.left + const originTop = obj.top + addCanvasMouseEventListener('mouse:up', (e) => { obj.set({ lockMovementX: true, lockMovementY: true, }) initEvent() + obj.setCoords() + updateGroupObjectCoords(obj, originLeft, originTop) + // canvas?.renderAll() }) - - obj.setCoords() - canvas?.renderAll() } } @@ -561,8 +553,6 @@ export function useCommonUtils() { if (obj) { let clonedObj = null - console.log(obj) - obj.clone((cloned) => { clonedObj = cloned }) @@ -623,39 +613,28 @@ export function useCommonUtils() { if (obj) canvas.remove(...obj) } + //선택된 그룹객체 restore 하고 item으로 다시 그리고 그 그린 객체 가지고 수정해서 재그룹화 시킨다 + const changeDimensionExtendLine = () => { const group = canvas?.getActiveObject() - const id = group.id - const textObj = canvas?.getObjects().filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0] - const items = group._objects - const originLineDirection = group.lineDirection - - let groupObj = [] - + const restoreGroup = group._restoreObjectsState() canvas?.remove(group) - - items.forEach((item) => { - item.set({ - selectable: true, - }) - canvas?.add(item) - }) canvas?.renderAll() + restoreGroup._objects.forEach((obj) => { + canvas?.add(obj) + }) + + const id = group.groupId + const originLineDirection = group.lineDirection + const textObj = canvas?.getObjects().filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0] const centerLine = canvas?.getObjects().filter((obj) => obj.name === 'centerLine' && obj.id === id)[0] const extendLine = canvas?.getObjects().filter((obj) => obj.name === 'extendLine' && obj.id === id) const arrows = canvas?.getObjects().filter((obj) => obj.name === 'arrow' && obj.id === id) const originX = centerLine.x1 const originY = centerLine.y1 - - const lineOptions = { - stroke: dimensionSettings.color, - strokeWidth: dimensionSettings.pixel, - selectable: true, - originX: 'center', - originY: 'center', - } + let reGroupObj = [] addCanvasMouseEventListener('mouse:down', (e) => { const pointer = canvas?.getPointer(e.e) @@ -668,37 +647,21 @@ export function useCommonUtils() { y2: pointer.y, }) - centerLine.setCoords() - canvas?.renderAll() - const differenceY = centerLine.y1 - originY - arrows.forEach((arrow) => { - canvas?.remove(arrow) + extendLine.forEach((obj) => { + obj.set({ + x1: obj.x1, + y1: originY, + x2: obj.x2, + y2: differenceY > 0 ? pointer.y + 20 : pointer.y - 20, + }) }) - const { paddingX, paddingX2, paddingY, paddingY2, angle1, angle2 } = calcDimensionPosition( - originLineDirection, - centerLine.x1, - pointer.y, - centerLine.x2, - pointer.y, - ) - - const newArrow1 = createDimensionArrow(paddingX, paddingY, angle1, id) - const newArraw2 = createDimensionArrow(paddingX2, paddingY2, angle2, id) - canvas?.add(newArrow1, newArraw2) - - groupObj.push(centerLine, newArrow1, newArraw2) - - extendLine.forEach((line) => canvas?.remove(line)) - - const newExtendLine = createDimensionExtendLine(centerLine, originLineDirection, differenceY) - - newExtendLine.forEach((line) => { - const extendLine = new fabric.Line(line, { ...lineOptions, name: 'extendLine', id: id }) - canvas.add(extendLine) - groupObj.push(extendLine) + arrows.forEach((arrow) => { + arrow.set({ + top: pointer.y, + }) }) textObj.set({ @@ -713,37 +676,21 @@ export function useCommonUtils() { y2: centerLine.y2, }) - centerLine.setCoords() - canvas?.renderAll() - const differenceX = centerLine.x1 - originX - arrows.forEach((arrow) => { - canvas?.remove(arrow) + extendLine.forEach((obj) => { + obj.set({ + x1: originX, + y1: obj.y1, + x2: differenceX > 0 ? pointer.x + 20 : pointer.x - 20, + y2: obj.y2, + }) }) - const { paddingX, paddingX2, paddingY, paddingY2, angle1, angle2 } = calcDimensionPosition( - originLineDirection, - pointer.x, - centerLine.y1, - pointer.x, - centerLine.y2, - ) - - const newArrow1 = createDimensionArrow(paddingX, paddingY, angle1, id) - const newArraw2 = createDimensionArrow(paddingX2, paddingY2, angle2, id) - canvas?.add(newArrow1, newArraw2) - - groupObj.push(centerLine, newArrow1, newArraw2) - - extendLine.forEach((line) => canvas?.remove(line)) - - const newExtendLine = createDimensionExtendLine(centerLine, originLineDirection, differenceX) - - newExtendLine.forEach((line) => { - const extendLine = new fabric.Line(line, { ...lineOptions, name: 'extendLine', id: id }) - canvas.add(extendLine) - groupObj.push(extendLine) + arrows.forEach((arrow) => { + arrow.set({ + left: pointer.x, + }) }) textObj.set({ @@ -752,19 +699,60 @@ export function useCommonUtils() { textObj.setCoords() } - const reGroup = new fabric.Group(groupObj, { + reGroupObj.push(centerLine, ...extendLine, ...arrows, textObj) + canvas?.remove(centerLine, ...extendLine, ...arrows, textObj) + + const reGroup = new fabric.Group(reGroupObj, { name: 'dimensionLine', selectable: true, - originX: 'center', - originY: 'center', lineDirection: originLineDirection, - id: id, + groupId: id, }) + + reGroupObj = [] canvas.add(reGroup) initEvent() }) } + // 그룹 이동 시 라인 및 각 객체의 좌표를 절대 좌표로 업데이트하는 함수 + function updateGroupObjectCoords(group, originLeft, originTop) { + const diffrenceLeft = group.left - originLeft + const diffrenceTop = group.top - originTop + + group.getObjects().forEach((obj) => { + // 그룹 내 객체의 절대 좌표를 계산 + + const originObjLeft = obj.left + const originObjTop = obj.top + + if (obj.type === 'line') { + // Line 객체의 경우, x1, y1, x2, y2 절대 좌표 계산 + + obj.set({ + x1: obj.x1 + diffrenceLeft, + y1: obj.y1 + diffrenceTop, + x2: obj.x2 + diffrenceLeft, + y2: obj.y2 + diffrenceTop, + }) + + obj.set({ + left: originObjLeft, + top: originObjTop, + }) + } else { + // 다른 객체의 경우 left, top 절대 좌표 설정 + obj.set({ + ...obj, + left: obj.left, + top: obj.top, + }) + } + obj.setCoords() // 좌표 반영 + canvas?.renderAll() + }) + } + return { commonFunctions, dimensionSettings, diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index ee3439f2..11d8e4f9 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -38,6 +38,8 @@ export function usePlan() { const str = JSON.stringify(objs) + console.log(str) + // canvas?.clear() return str @@ -56,6 +58,31 @@ export function usePlan() { */ const currentCanvasData = () => { removeMouseLines() + + const groups = canvas.getObjects().filter((obj) => obj.type === 'group') + + if (groups.length > 0) { + groups.forEach((group) => { + canvas?.remove(group) + canvas?.renderAll() + const restore = group._restoreObjectsState() + + restore._objects.forEach((obj) => { + obj.set({ + ...obj, + groupYn: true, + groupName: group.name, + lineDirection: group.lineDirection, + }) + + canvas?.add(obj) + obj.setCoords() + canvas?.requestRenderAll() + canvas?.renderAll() + }) + }) + } + return addCanvas() }