diff --git a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx index 7f981dce..59c0ead4 100644 --- a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx +++ b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx @@ -49,9 +49,8 @@ export default function DimensionLineSetting(props) { resultText = calculateLength(basicLength, slopeInput1.angleValue).toFixed(0) if (slopeInput2) { - const angle = slopeInput1 + slopeInput2 - const length = calculateLength(basicLength, angle) - resultText = length.toFixed(2) + const length = calculateLength(basicLength, slopeInput1.angleValue, slopeInput2.angleValue) + resultText = length.toFixed(0) } } } @@ -71,11 +70,18 @@ export default function DimensionLineSetting(props) { } function calculateLength(originalLength, angle) { - const angleInRadians = angle * (Math.PI / 180) // 각도를 라디안으로 변환 + const angleInRadians = angle * (Math.PI / 180) const result = Math.sqrt(Math.pow(originalLength * Math.tan(angleInRadians), 2) + Math.pow(originalLength, 2)) return result } + function calculateLength(originalLength, angle1, angle2) { + const numerator = Math.sqrt(Math.pow(angle1, 2) + 100 + Math.pow((10 * angle1) / angle2, 2)) * originalLength + const denominator = Math.sqrt(Math.pow((10 * angle1) / angle2, 2) + 100) + const result = numerator / denominator + return result + } + return (
diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx index fd172aee..af239258 100644 --- a/src/components/floor-plan/modal/object/SizeSetting.jsx +++ b/src/components/floor-plan/modal/object/SizeSetting.jsx @@ -5,7 +5,9 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import { usePopup } from '@/hooks/usePopup' import { contextPopupPositionState } from '@/store/popupAtom' -import { useState } from 'react' +import { useRef, useState, useEffect } from 'react' +import { useObjectBatch } from '@/hooks/object/useObjectBatch' +import { useEvent } from '@/hooks/useEvent' export default function SizeSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -13,6 +15,23 @@ export default function SizeSetting(props) { const { id, pos = contextPopupPosition, target } = props const { getMessage } = useMessage() const { closePopup } = usePopup() + const { reSizeObject } = useObjectBatch() + + const widthRef = useRef(null) + const heightRef = useRef(null) + + const { initEvent } = useEvent() + + useEffect(() => { + initEvent() + }, []) + + const handleReSizeObject = () => { + const width = widthRef.current.value + const height = heightRef.current.value + + reSizeObject(settingTarget, target, width, height) + } return ( @@ -28,11 +47,11 @@ export default function SizeSetting(props) {
- + mm
- + mm
@@ -41,11 +60,11 @@ export default function SizeSetting(props) {
- + mm
- + mm
@@ -60,7 +79,9 @@ export default function SizeSetting(props) {
- +
diff --git a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx index f2a8a1f0..34a87e44 100644 --- a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx +++ b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx @@ -38,7 +38,7 @@ const TriangleDormer = forwardRef((props, refs) => {
- +
mm
diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js index 0e187b1e..356c100e 100644 --- a/src/hooks/common/useCommonUtils.js +++ b/src/hooks/common/useCommonUtils.js @@ -547,7 +547,7 @@ export function useCommonUtils() { initEvent() obj.setCoords() updateGroupObjectCoords(obj, originLeft, originTop) - // canvas?.renderAll() + canvas?.renderAll() }) } } @@ -585,6 +585,10 @@ export function useCommonUtils() { editable: false, id: uuidv4(), //복사된 객체라 새로 따준다 }) + + //객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다 + if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() }) + initEvent() }) } @@ -748,7 +752,6 @@ export function useCommonUtils() { } else { // 다른 객체의 경우 left, top 절대 좌표 설정 obj.set({ - ...obj, left: obj.left, top: obj.top, }) diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index c9b4cd3b..c55841c6 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -43,8 +43,12 @@ export function useObjectBatch({ isHidden, setIsHidden }) { // 클릭한 위치에 있는 객체 찾기 const clickedObject = objects.find((obj) => { + console.log(obj) + if (obj.type === 'QPolygon') { - return obj.inPolygon({ x: pointer.x, y: pointer.y }) + const polygon = pointsToTurfPolygon(obj.getCurrentPoints()) + const turfPointer = turf.point([pointer.x, pointer.y]) + return turf.booleanPointInPolygon(turfPointer, polygon) } else { return obj.containsPoint(pointer) } @@ -403,7 +407,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) { }) //오프셋이 있을땐 같이 도머로 만든다 const leftTriangle = new QPolygon(splitedTriangle[0], { - fill: 'transparent', + fill: 'white', stroke: 'black', strokeWidth: 1, selectable: true, @@ -422,7 +426,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) { }) const rightTriangle = new QPolygon(splitedTriangle[1], { - fill: 'transparent', + fill: 'white', stroke: 'black', strokeWidth: 1, selectable: true, @@ -450,7 +454,33 @@ export function useObjectBatch({ isHidden, setIsHidden }) { drawDirectionArrow(leftTriangle) drawDirectionArrow(rightTriangle) - const objectGroup = new fabric.Group([leftTriangle, rightTriangle], { + let offsetPolygon + + if (offsetRef > 0) { + canvas?.remove(dormer) + + offsetPolygon = new QPolygon(triangleToPolygon(dormer), { + selectable: true, + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + viewLengthText: true, + name: 'triangleDormerOffset', + id: id, + fill: 'rgba(255, 255, 255, 0.6)', + stroke: 'black', + strokeWidth: 1, + originX: 'center', + originY: 'center', + fontSize: lengthTextFont.fontSize.value, + fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontWeight: lengthTextFont.fontWeight.value, + }) + } + + const groupPolygon = offsetPolygon ? [leftTriangle, rightTriangle, offsetPolygon] : [leftTriangle, rightTriangle] + + const objectGroup = new fabric.Group(groupPolygon, { subTargetCheck: true, name: dormerName, id: id, @@ -796,10 +826,102 @@ export function useObjectBatch({ isHidden, setIsHidden }) { return [leftPoints, rightPoints] } + const reSizeObject = (side, target, width, height) => { + console.log('reSizeTarget', target) + + target.getObjects().forEach((obj) => { + console.log('obj', obj.type) + }) + + const objectWidth = target.width + const objectHeight = target.height + const changeWidth = (width / 10 / objectWidth).toFixed(2) + const changeHeight = (height / 10 / objectHeight).toFixed(2) + let sideX = 'left' + let sideY = 'top' + + //그룹 중심점 변경 + if (side === 2) { + sideX = 'right' + sideY = 'top' + } else if (side === 3) { + sideX = 'left' + sideY = 'bottom' + } else if (side === 4) { + sideX = 'right' + sideY = 'bottom' + } + + //변경 전 좌표 + const newCoords = target.getPointByOrigin(sideX, sideY) + + target.set({ + ...target, + originX: sideX, + originY: sideY, + left: newCoords.x, + top: newCoords.y, + }) + + target.setCoords() + canvas?.renderAll() //변경 좌표를 한번 적용 + + target.scaleX = changeWidth === 0 ? 1 : changeWidth + target.scaleY = changeHeight === 0 ? 1 : changeHeight + + //크기 변경후 좌표를 재 적용 + const changedCoords = target.getPointByOrigin('center', 'center') + + target.set({ + ...target, + originX: 'center', + originY: 'center', + left: changedCoords.x, + top: changedCoords.y, + }) + + if (target.name === 'roof') { + //얘는 일단 도머에 적용함 + target._objects.forEach((obj) => { + setSurfaceShapePattern(obj) + }) + } + // target.setCoords() + canvas.renderAll() + + // reGroupObject(target) + } + + const reGroupObject = (groupObj) => { + groupObj._restoreObjectsState() //이건 실행만 되도 그룹이 변경됨 + const reGroupObjects = [] + + groupObj._objects.forEach((obj) => { + const newObj = new QPolygon(obj.getCurrentPoints(), { + ...obj, + points: obj.getCurrentPoints(), + scaleX: 1, + scaleY: 1, + }) + reGroupObjects.push(newObj) + canvas.remove(obj) + }) + + const reGroup = new fabric.Group(reGroupObjects, { + subTargetCheck: true, + name: groupObj.name, + id: groupObj.id, + groupYn: true, + }) + canvas?.add(reGroup) + canvas?.remove(groupObj) + } + return { applyOpeningAndShadow, applyDormers, splitDormerTriangle, splitDormerPentagon, + reSizeObject, } } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 3fd1bb0e..f8dc92b5 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -273,16 +273,19 @@ export function useContextMenu() { id: 'dormerRemove', shortcut: ['d', 'D'], name: `${getMessage('contextmenu.remove')}(D)`, + fn: () => deleteObject(), }, { id: 'dormerMove', shortcut: ['m', 'M'], name: `${getMessage('contextmenu.move')}(M)`, + fn: () => moveObject(), }, { id: 'dormerCopy', shortcut: ['c', 'C'], name: `${getMessage('contextmenu.copy')}(C)`, + fn: () => copyObject(), }, { id: 'roofMaterialEdit', @@ -451,7 +454,7 @@ export function useContextMenu() { ], ]) break - case 'dimensionLine': + case 'dimensionGroup': setContextMenu([ [ { diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 897c8a54..bddebc63 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -55,40 +55,40 @@ export function usePlan() { /** * 현재 캔버스에 그려진 데이터를 추출 */ - const currentCanvasData = () => { + const currentCanvasData = (mode = '') => { removeMouseLines() - const groups = canvas.getObjects().filter((obj) => obj.type === 'group') + if (mode === 'save') { + const groups = canvas.getObjects().filter((obj) => obj.type === 'group') - console.log('groups', groups) - - 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, - groupId: group.id, - }) - - //디렉션이 있는 경우에만 - if (group.lineDirection) { - obj.set({ - lineDirection: group.lineDirection, - }) - } - - canvas?.add(obj) - obj.setCoords() + 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, + groupId: group.id, + }) + + //디렉션이 있는 경우에만 + if (group.lineDirection) { + obj.set({ + lineDirection: group.lineDirection, + }) + } + + canvas?.add(obj) + obj.setCoords() + canvas?.renderAll() + }) }) - }) + } } return addCanvas() @@ -172,7 +172,7 @@ export function usePlan() { * 페이지 내 캔버스를 저장 */ const saveCanvas = async (userId) => { - const canvasStatus = currentCanvasData() + const canvasStatus = currentCanvasData('save') initCanvasPlans.some((plan) => plan.id === currentCanvasPlan.id) ? await putCanvasStatus(canvasStatus) : await postCanvasStatus(userId, canvasStatus)