배치면 오브젝트 이동 기능 추가
This commit is contained in:
parent
524eab2130
commit
daf6bd4e00
@ -137,6 +137,22 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
})
|
||||
})
|
||||
|
||||
this.on('polygonMoved', () => {
|
||||
//폴리곤일때만 사용
|
||||
let matrix = this.calcTransformMatrix()
|
||||
|
||||
let transformedPoints = this.get('points')
|
||||
.map((p) => {
|
||||
return new fabric.Point(p.x - this.pathOffset.x, p.y - this.pathOffset.y)
|
||||
})
|
||||
.map((p) => {
|
||||
return fabric.util.transformPoint(p, matrix)
|
||||
})
|
||||
this.set('points', transformedPoints)
|
||||
this.set('pathOffset', { x: this.left, y: this.top })
|
||||
this.setCoords()
|
||||
})
|
||||
|
||||
// polygon.fillCell({ width: 50, height: 30, padding: 10 })
|
||||
},
|
||||
|
||||
@ -211,6 +227,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
|
||||
let points = this.getCurrentPoints()
|
||||
|
||||
this.texts = []
|
||||
points.forEach((start, i) => {
|
||||
const end = points[(i + 1) % points.length]
|
||||
const dx = end.x - start.x
|
||||
|
||||
@ -8,6 +8,8 @@ import { contextPopupPositionState } from '@/store/popupAtom'
|
||||
import { useRef, useState, useEffect } from 'react'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { BATCH_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
|
||||
export default function SizeSetting(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
@ -15,8 +17,8 @@ export default function SizeSetting(props) {
|
||||
const { id, pos = contextPopupPosition, target } = props
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
const { reSizeObjectBatch } = useObjectBatch({})
|
||||
|
||||
const { resizeObjectBatch } = useObjectBatch({})
|
||||
const { reSizePolygon } = useSurfaceShapeBatch()
|
||||
const widthRef = useRef(null)
|
||||
const heightRef = useRef(null)
|
||||
|
||||
@ -30,7 +32,15 @@ export default function SizeSetting(props) {
|
||||
const width = widthRef.current.value
|
||||
const height = heightRef.current.value
|
||||
|
||||
reSizeObjectBatch(settingTarget, target, width, height)
|
||||
if (
|
||||
target.name === BATCH_TYPE.OPENING ||
|
||||
target.name === BATCH_TYPE.SHADOW ||
|
||||
target.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
target.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||
target.name === POLYGON_TYPE.ROOF
|
||||
) {
|
||||
resizeObjectBatch(settingTarget, target, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -100,8 +100,6 @@ export function useCanvasConfigInitialize() {
|
||||
const groups = canvas.getObjects().filter((obj) => obj.groupYn && obj.name === 'dimensionGroup')
|
||||
const groupIds = []
|
||||
|
||||
console.log('groupDimensionInit', groups)
|
||||
|
||||
groups.forEach((group) => {
|
||||
if (!groupIds.includes(group.id)) {
|
||||
groupIds.push(group.id)
|
||||
@ -157,6 +155,7 @@ export function useCanvasConfigInitialize() {
|
||||
//그룹아이디로 캔버스의 객체를 조회함
|
||||
const groupObjects = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)
|
||||
const objectsName = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)[0].groupName
|
||||
const objectsParentId = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)[0].parentId
|
||||
|
||||
let objectArray = []
|
||||
|
||||
@ -181,8 +180,14 @@ export function useCanvasConfigInitialize() {
|
||||
lockMovementY: true,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
parentId: objectsParentId,
|
||||
})
|
||||
canvas.add(group)
|
||||
|
||||
//그룹 객체 재그룹 완료
|
||||
group.getObjects().forEach((obj) => {
|
||||
obj.fire('modified')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -33,10 +33,16 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}, [])
|
||||
|
||||
const dbClickEvent = () => {
|
||||
console.log('dbClickEvent 실행')
|
||||
const dormerObject = canvas.getObjects().filter((obj) => obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER)
|
||||
|
||||
console.log('dormerObject', dormerObject)
|
||||
|
||||
if (dormerObject) {
|
||||
canvas.off('mouse:dblclick')
|
||||
canvas.on('mouse:dblclick', (e) => {
|
||||
console.log('event', e)
|
||||
|
||||
if (e.target && e.target instanceof fabric.Group) {
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
const objects = e.target._objects
|
||||
@ -71,7 +77,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
let rect, isDown, origX, origY
|
||||
let selectedSurface
|
||||
//프리입력
|
||||
console.log('useObjectBatch', isHidden)
|
||||
|
||||
if (selectedType === INPUT_TYPE.FREE) {
|
||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||
isDown = true
|
||||
@ -160,7 +166,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
|
||||
@ -204,6 +210,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
parentId: selectedSurface.id,
|
||||
})
|
||||
|
||||
//개구냐 그림자냐에 따라 변경
|
||||
@ -241,7 +248,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
@ -483,6 +490,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
subTargetCheck: true,
|
||||
name: dormerName,
|
||||
id: id,
|
||||
parentId: selectedSurface.id,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
@ -693,6 +703,10 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
subTargetCheck: true,
|
||||
name: dormerName,
|
||||
id: id,
|
||||
parentId: selectedSurface.id,
|
||||
groupYn: true,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
@ -858,9 +872,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
return [leftPoints, rightPoints]
|
||||
}
|
||||
|
||||
const reSizeObjectBatch = (side, target, width, height) => {
|
||||
const targetObj = canvas.getActiveObject()
|
||||
|
||||
const resizeObjectBatch = (side, target, width, height) => {
|
||||
const objectWidth = target.width
|
||||
const objectHeight = target.height
|
||||
const changeWidth = (width / 10 / objectWidth).toFixed(2)
|
||||
@ -884,7 +896,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const newCoords = target.getPointByOrigin(sideX, sideY)
|
||||
|
||||
target.set({
|
||||
...target,
|
||||
originX: sideX,
|
||||
originY: sideY,
|
||||
left: newCoords.x,
|
||||
@ -894,8 +905,8 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
target.setCoords()
|
||||
canvas?.renderAll() //변경 좌표를 한번 적용
|
||||
|
||||
target.scaleX = changeWidth === 0 ? 1 : changeWidth
|
||||
target.scaleY = changeHeight === 0 ? 1 : changeHeight
|
||||
target.scaleX = changeWidth || 1
|
||||
target.scaleY = changeHeight || 1
|
||||
|
||||
//크기 변경후 좌표를 재 적용
|
||||
const changedCoords = target.getPointByOrigin('center', 'center')
|
||||
@ -910,9 +921,12 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
if (target.name === 'roof') {
|
||||
//얘는 일단 도머에 적용함
|
||||
target._objects.forEach((obj) => {
|
||||
setSurfaceShapePattern(obj)
|
||||
})
|
||||
if (target.type === 'group') {
|
||||
target._objects.forEach((obj) => setSurfaceShapePattern(obj))
|
||||
} else {
|
||||
setSurfaceShapePattern(target)
|
||||
target.fire('modified')
|
||||
}
|
||||
}
|
||||
// target.setCoords()
|
||||
canvas.renderAll()
|
||||
@ -923,27 +937,29 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
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,
|
||||
texts: [],
|
||||
})
|
||||
reGroupObjects.push(newObj)
|
||||
canvas.remove(obj)
|
||||
|
||||
if (obj.direction) {
|
||||
drawDirectionArrow(obj)
|
||||
}
|
||||
newObj.fire('modified')
|
||||
})
|
||||
|
||||
const reGroup = new fabric.Group(reGroupObjects, {
|
||||
subTargetCheck: true,
|
||||
name: groupObj.name,
|
||||
id: groupObj.id,
|
||||
groupYn: true,
|
||||
parentId: groupObj.parentId,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(reGroup)
|
||||
canvas?.remove(groupObj)
|
||||
@ -965,7 +981,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
})
|
||||
initEvent()
|
||||
obj.setCoords()
|
||||
reGroupObject(obj)
|
||||
if (obj.type === 'group') reGroupObject(obj)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -975,7 +991,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
applyDormers,
|
||||
splitDormerTriangle,
|
||||
splitDormerPentagon,
|
||||
reSizeObjectBatch,
|
||||
resizeObjectBatch,
|
||||
moveObjectBatch,
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,12 @@ import { useEvent } from '@/hooks/useEvent'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||
import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { fontSelector } from '@/store/fontAtom'
|
||||
|
||||
export function useSurfaceShapeBatch() {
|
||||
const { getMessage } = useMessage()
|
||||
const { drawDirectionArrow } = usePolygon()
|
||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const globalPitch = useRecoilValue(globalPitchState)
|
||||
@ -598,8 +600,214 @@ export function useSurfaceShapeBatch() {
|
||||
})
|
||||
}
|
||||
|
||||
const findAllChildren = (parentId) => {
|
||||
let allChildren = []
|
||||
|
||||
// 직계 자식 객체들 찾기
|
||||
const directChildren = canvas.getObjects().filter((obj) => obj.parentId === parentId)
|
||||
|
||||
directChildren.forEach((child) => {
|
||||
allChildren.push(child) // 현재 자식 추가
|
||||
|
||||
// 자식이 그룹인 경우
|
||||
if (child.type === 'group') {
|
||||
// 그룹 내부의 객체들 추가
|
||||
child.getObjects().forEach((groupItem) => {
|
||||
allChildren.push(groupItem)
|
||||
// 그룹 내부 객체의 자식들도 찾기
|
||||
const nestedChildren = findAllChildren(groupItem.id)
|
||||
allChildren.push(...nestedChildren)
|
||||
})
|
||||
}
|
||||
|
||||
// 현재 자식의 하위 자식들 찾기
|
||||
const childrenOfChild = findAllChildren(child.id)
|
||||
allChildren.push(...childrenOfChild)
|
||||
})
|
||||
|
||||
// 중복 제거하여 반환
|
||||
return [...new Set(allChildren)]
|
||||
}
|
||||
|
||||
const findGroupObjects = (parentId) => {
|
||||
let groupObjectsArray = []
|
||||
|
||||
// 직계 자식 객체들 찾기
|
||||
const directChildren = canvas.getObjects().filter((obj) => obj.parentId === parentId)
|
||||
|
||||
// 각 자식 객체에 대해 처리
|
||||
directChildren.forEach((child) => {
|
||||
groupObjectsArray.push(child) // 현재 자식 추가
|
||||
|
||||
// 자식이 그룹인 경우 그룹 내부 객체들도 처리
|
||||
if (child.type === 'group') {
|
||||
child.getObjects().forEach((groupItem) => {
|
||||
// 그룹 내부 각 아이템의 하위 객체들 찾기
|
||||
const nestedObjects = findGroupObjects(groupItem.id)
|
||||
groupObjectsArray.push(...nestedObjects)
|
||||
})
|
||||
}
|
||||
|
||||
// 일반 자식의 하위 객체들 찾기
|
||||
const childObjects = findGroupObjects(child.id)
|
||||
groupObjectsArray.push(...childObjects)
|
||||
})
|
||||
|
||||
return groupObjectsArray
|
||||
}
|
||||
|
||||
function getAllRelatedObjects(id) {
|
||||
const result = []
|
||||
const map = new Map()
|
||||
|
||||
// Create a map of objects by their id
|
||||
canvas.getObjects().forEach((obj) => {
|
||||
map.set(obj.id, obj)
|
||||
})
|
||||
|
||||
// Helper function to recursively find all related objects
|
||||
function findRelatedObjects(id) {
|
||||
const obj = map.get(id)
|
||||
if (obj) {
|
||||
result.push(obj)
|
||||
canvas.getObjects().forEach((o) => {
|
||||
if (o.parentId === id) {
|
||||
findRelatedObjects(o.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Start the search with the given parentId
|
||||
findRelatedObjects(id)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const moveSurfaceShapeBatch = () => {
|
||||
const roof = canvas.getActiveObject()
|
||||
|
||||
if (roof) {
|
||||
let isDragging = false
|
||||
|
||||
const childrenObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id)
|
||||
|
||||
console.log('childrenObjects', childrenObjects)
|
||||
|
||||
// const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id && obj.type === 'group')
|
||||
|
||||
// const ungroupObjects = [] // 그룹 해제된 객체들
|
||||
// const groupChildObjects = []
|
||||
|
||||
// groupObjects.forEach((obj) => {
|
||||
// obj._restoreObjectsState()
|
||||
// obj.getObjects().forEach((o) => {
|
||||
// o.set({
|
||||
// ungroupYn: true,
|
||||
// })
|
||||
// canvas.add(o)
|
||||
// ungroupObjects.push(o)
|
||||
// })
|
||||
// canvas.remove(obj)
|
||||
// })
|
||||
|
||||
// const childObjects = findAllChildren(roof.id)
|
||||
// groupObjects.forEach((obj) => {
|
||||
// groupChildObjects.push(...obj.getObjects())
|
||||
// })
|
||||
|
||||
// console.log('ungroupObjects', ungroupObjects)
|
||||
// console.log('childObjects', childObjects)
|
||||
// console.log('groupChildObjects', groupChildObjects)
|
||||
|
||||
// const children = canvas.getObjects().filter((obj) => obj.parentId === roof.id)
|
||||
// let grandChildren = []
|
||||
|
||||
// children.forEach((child) => {
|
||||
// if (child.type === 'group') {
|
||||
// child.getObjects().forEach((grandChild) => {
|
||||
// const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === grandChild.id)
|
||||
// grandChildren.push(...groupObjects)
|
||||
// })
|
||||
// } else {
|
||||
// grandChildren.push(...canvas.getObjects().filter((obj) => obj.parentId === child.id))
|
||||
// }
|
||||
// })
|
||||
|
||||
const selectionArray = [roof, ...childrenObjects]
|
||||
|
||||
const selection = new fabric.ActiveSelection(selectionArray, {
|
||||
canvas: canvas,
|
||||
draggable: true,
|
||||
lockMovementX: false, // X축 이동 허용
|
||||
lockMovementY: false, // Y축 이동 허용
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
|
||||
canvas.setActiveObject(selection)
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
isDragging = false
|
||||
canvas.selection = true
|
||||
|
||||
canvas.discardActiveObject() // 모든 선택 해제
|
||||
canvas.requestRenderAll() // 화면 업데이트
|
||||
|
||||
selection.getObjects().forEach((obj) => {
|
||||
obj.set({
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
})
|
||||
obj.setCoords()
|
||||
|
||||
if (obj.type === 'group') {
|
||||
reGroupObject(obj)
|
||||
}
|
||||
})
|
||||
|
||||
canvas.renderAll()
|
||||
roof.fire('polygonMoved')
|
||||
if (roof.type === 'group') reGroupObject(obj)
|
||||
drawDirectionArrow(roof)
|
||||
initEvent()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if (obj.direction) {
|
||||
drawDirectionArrow(obj)
|
||||
}
|
||||
})
|
||||
|
||||
const reGroup = new fabric.Group(reGroupObjects, {
|
||||
subTargetCheck: true,
|
||||
name: groupObj.name,
|
||||
id: groupObj.id,
|
||||
groupYn: true,
|
||||
parentId: groupObj.parentId,
|
||||
})
|
||||
canvas?.add(reGroup)
|
||||
canvas?.remove(groupObj)
|
||||
}
|
||||
|
||||
return {
|
||||
applySurfaceShape,
|
||||
deleteAllSurfacesAndObjects,
|
||||
moveSurfaceShapeBatch,
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import RowRemove from '@/components/floor-plan/modal/module/row/RowRemove'
|
||||
import RowInsert from '@/components/floor-plan/modal/module/row/RowInsert'
|
||||
import CircuitNumberEdit from '@/components/floor-plan/modal/module/CircuitNumberEdit'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
|
||||
export function useContextMenu() {
|
||||
const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴
|
||||
@ -50,7 +51,7 @@ export function useContextMenu() {
|
||||
const [column, setColumn] = useState(null)
|
||||
const { handleZoomClear } = useCanvasEvent()
|
||||
const { moveObjectBatch } = useObjectBatch({})
|
||||
|
||||
const { moveSurfaceShapeBatch } = useSurfaceShapeBatch()
|
||||
const currentMenuSetting = () => {
|
||||
switch (currentMenu) {
|
||||
case MENU.PLAN_DRAWING:
|
||||
@ -256,6 +257,7 @@ export function useContextMenu() {
|
||||
}, [currentContextMenu])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('currentObject', currentObject)
|
||||
if (currentObject?.name) {
|
||||
console.log(currentObject?.name)
|
||||
switch (currentObject.name) {
|
||||
@ -305,22 +307,25 @@ export function useContextMenu() {
|
||||
{
|
||||
id: 'sizeEdit',
|
||||
name: '사이즈 변경',
|
||||
component: <SizeSetting id={popupId} />,
|
||||
component: <SizeSetting id={popupId} target={currentObject} />,
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialRemove',
|
||||
shortcut: ['d', 'D'],
|
||||
name: `${getMessage('contextmenu.remove')}(D)`,
|
||||
fn: () => deleteObject(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialMove',
|
||||
shortcut: ['m', 'M'],
|
||||
name: `${getMessage('contextmenu.move')}(M)`,
|
||||
fn: () => moveSurfaceShapeBatch(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialCopy',
|
||||
shortcut: ['c', 'C'],
|
||||
name: `${getMessage('contextmenu.copy')}(C)`,
|
||||
fn: () => copyObject(),
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
@ -77,11 +77,9 @@ export function usePlan() {
|
||||
})
|
||||
|
||||
//디렉션이 있는 경우에만
|
||||
if (group.lineDirection) {
|
||||
obj.set({
|
||||
lineDirection: group.lineDirection,
|
||||
})
|
||||
}
|
||||
if (group.lineDirection) obj.set({ lineDirection: group.lineDirection })
|
||||
//부모객체가 있으면 (면형상 위에 도머등..)
|
||||
if (group.parentId) obj.set({ parentId: group.parentId })
|
||||
|
||||
canvas?.add(obj)
|
||||
obj.setCoords()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user