diff --git a/src/common/common.js b/src/common/common.js
index ca472a11..0fa678db 100644
--- a/src/common/common.js
+++ b/src/common/common.js
@@ -198,6 +198,10 @@ export const SAVE_KEY = [
'isChidory',
'textVisible',
'groupPoints',
+ 'fontSize',
+ 'fontStyle',
+ 'fontWeight',
+ 'dormerAttributes',
]
-export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
+export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx
index da241db1..b6bdbfef 100644
--- a/src/components/estimate/Estimate.jsx
+++ b/src/components/estimate/Estimate.jsx
@@ -46,7 +46,6 @@ export default function Estimate({}) {
const [selection, setSelection] = useState(new Set())
//견적특이사항 접고 펼치기
- // const [hidden, setHidden] = useState(false)
const [hidden, setHidden] = useState(true)
//아이템 자동완성 리스트
@@ -569,7 +568,7 @@ export default function Estimate({}) {
return selection.size === getAbledItems(estimateContextState.itemList).length
}
- //row 체크박스 컨트롤
+ //아이템row 체크박스 컨트롤
const onChangeSelect = (dispOrder) => {
const newSelection = new Set(selection)
if (newSelection.has(dispOrder)) {
@@ -581,10 +580,6 @@ export default function Estimate({}) {
setSelection(newSelection)
}
- function formatNumberWithComma(number) {
- return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
- }
-
//주택PKG input 변경
const onChangePkgAsp = (value) => {
if (estimateContextState.estimateType === 'YJSS') {
@@ -1140,6 +1135,7 @@ export default function Estimate({}) {
}
}
}, [estimateContextState])
+
return (
diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx
index 2b0e9c03..d4b979c7 100644
--- a/src/components/floor-plan/modal/basic/step/Placement.jsx
+++ b/src/components/floor-plan/modal/basic/step/Placement.jsx
@@ -59,7 +59,7 @@ const Placement = forwardRef((props, refs) => {
}
//모듈 배치면 생성
- if (moduleSelectionData.module.itemList.length > 1) {
+ if (isObjectNotEmpty(moduleSelectionData.module) && moduleSelectionData.module.itemList.length > 1) {
setIsMultiModule(true)
}
}
diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx
index 909aad99..b602f163 100644
--- a/src/components/floor-plan/modal/object/ObjectSetting.jsx
+++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx
@@ -24,7 +24,6 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
const { closePopup } = usePopup()
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
-
//오브젝트 배치로 넘어오면 면형상 선택 불가
useEffect(() => {
canvas.discardActiveObject()
@@ -54,15 +53,41 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
const applyObject = () => {
if (surfaceShapePolygons.length === 0) {
- swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
return
}
//개구배치, 그림자배치
if (buttonAct === 1 || buttonAct === 2) {
- applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons)
+ applyOpeningAndShadow(objectPlacement, buttonAct)
} else {
- applyDormers(dormerPlacement, buttonAct, surfaceShapePolygons)
+ const height = dormerPlacement.heightRef.current !== null ? dormerPlacement.heightRef.current.value / 10 : 0
+ const width = dormerPlacement.widthRef.current !== null ? dormerPlacement.widthRef.current.value / 10 : 0 //triangle일때는 없음
+ const pitch = dormerPlacement.pitchRef.current !== null ? Number(dormerPlacement.pitchRef.current.value) : 0
+ const offsetRef =
+ dormerPlacement.offsetRef.current !== null
+ ? dormerPlacement.offsetRef.current.value === ''
+ ? 0
+ : parseInt(dormerPlacement.offsetRef.current.value) / 10
+ : 0
+ const offsetWidthRef =
+ dormerPlacement.offsetWidthRef.current !== null
+ ? dormerPlacement.offsetWidthRef.current.value === ''
+ ? 0
+ : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10
+ : 0
+ const directionRef = dormerPlacement.directionRef.current
+
+ const dormerParams = {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ }
+
+ applyDormers(dormerParams, buttonAct)
}
setIsHidden(true)
}
diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx
index dbc9d6e4..54075153 100644
--- a/src/components/main/ChangePasswordPop.jsx
+++ b/src/components/main/ChangePasswordPop.jsx
@@ -119,7 +119,11 @@ export default function ChangePasswordPop(props) {
},
})
} else {
- alert(res?.result?.resultMsg)
+ swalFire({
+ text: getMessage(res?.result?.resultMsg),
+ type: 'alert',
+ icon: 'error',
+ })
}
} else {
setIsGlobalLoading(false)
diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx
index 0a3be3ee..43446209 100644
--- a/src/components/management/Stuff.jsx
+++ b/src/components/management/Stuff.jsx
@@ -75,7 +75,10 @@ export default function Stuff() {
type: 'alert',
})
} catch (err) {
- alert(getMessage('stuff.detail.header.failCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.failCopy'),
+ type: 'alert',
+ })
} finally {
textArea.remove()
}
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx
index f4d7fbd4..266f1779 100644
--- a/src/components/management/StuffDetail.jsx
+++ b/src/components/management/StuffDetail.jsx
@@ -107,7 +107,6 @@ export default function StuffDetail() {
const [areaIdList, setAreaIdList] = useState([]) //발전시뮬레이션 리스트
- const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤
const [showAddressButtonValid, setShowAddressButtonValid] = useState(false) //주소검색팝업 활성화 컨트롤
const [showDesignRequestButtonValid, setShowDesignRequestButtonValid] = useState(false) //설계의뢰팝업 활성화 컨트롤
const [showWindSpeedButtonValid, setShowWindSpeedButtonValid] = useState(false) //풍속선택팝업 활성화 컨트롤
@@ -1094,8 +1093,6 @@ export default function StuffDetail() {
if (!formData.installHeight) {
errors.installHeight = true
}
-
- setIsFormValid(Object.keys(errors).length === 0 ? true : false)
} else {
//상세일떄 폼체크
const formData = form.getValues()
@@ -1140,8 +1137,6 @@ export default function StuffDetail() {
if (!formData.installHeight) {
errors.installHeight = true
}
-
- setIsFormValid(Object.keys(errors).length === 0 ? true : false)
}
}, [
_receiveUser,
diff --git a/src/components/management/StuffHeader.jsx b/src/components/management/StuffHeader.jsx
index d669ad7a..1f68d68a 100644
--- a/src/components/management/StuffHeader.jsx
+++ b/src/components/management/StuffHeader.jsx
@@ -4,7 +4,6 @@ import { useContext, useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage'
import dayjs from 'dayjs'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
-// import { ManagementContext } from '@/app/management/ManagementProvider'
import { useSwal } from '@/hooks/useSwal'
export default function StuffHeader() {
const { getMessage } = useMessage()
@@ -23,7 +22,10 @@ export default function StuffHeader() {
})
})
.catch(() => {
- alert(getMessage('stuff.detail.header.failCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.failCopy'),
+ type: 'alert',
+ })
})
} else {
// Use the 'out of viewport hidden text area' trick
@@ -44,7 +46,10 @@ export default function StuffHeader() {
type: 'alert',
})
} catch (err) {
- alert(getMessage('stuff.detail.header.failCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.failCopy'),
+ type: 'alert',
+ })
} finally {
textArea.remove()
}
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx
index 05c00a13..c00e8bd6 100644
--- a/src/components/management/StuffSearchCondition.jsx
+++ b/src/components/management/StuffSearchCondition.jsx
@@ -18,6 +18,7 @@ import { isObjectNotEmpty } from '@/util/common-utils'
import { SessionContext } from '@/app/SessionProvider'
import { QcastContext } from '@/app/QcastProvider'
+import { useSwal } from '@/hooks/useSwal'
export default function StuffSearchCondition() {
const router = useRouter()
@@ -73,17 +74,24 @@ export default function StuffSearchCondition() {
const [otherSaleStoreId, setOtherSaleStoreId] = useState('')
const { setIsGlobalLoading } = useContext(QcastContext)
+ const { swalFire } = useSwal()
// 조회
const onSubmit = () => {
let diff = dayjs(endDate).diff(startDate, 'day')
if (diff > 366) {
- return alert(getMessage('stuff.message.periodError'))
+ return swalFire({
+ text: getMessage('stuff.message.periodError'),
+ type: 'alert',
+ })
}
if (isNaN(diff)) {
- return alert(getMessage('stuff.message.periodError'))
+ return swalFire({
+ text: getMessage('stuff.message.periodError'),
+ type: 'alert',
+ })
}
setIsGlobalLoading(true)
diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx
index c22f4cb8..f35c6c53 100644
--- a/src/components/management/StuffSubHeader.jsx
+++ b/src/components/management/StuffSubHeader.jsx
@@ -49,20 +49,18 @@ export default function StuffSubHeader({ type }) {
const searchParams = useSearchParams()
const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set
- // url에 물건번호로 도면작성화면으로 이동
+ /**
+ * 도면작성은 플랜1번의 도면작성화면으로 이동하기 때문에 -> 플랜1번이 삭제가능으로 변경되서 planList의 0번째로!
+ * 1.물건작성하고 바로 -> planList 생성전. surface
+ * 2.물건이 여러건있을때 1번 플랜의 estimateDate 여부로 selectedMenu 셋팅
+ */
const moveFloorPlan = () => {
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
-
const param = {
- pid: '1',
+ pid: managementState?.planList?.length === 0 ? '1' : managementState?.planList[0].planNo,
objectNo: objectNo,
}
- /**
- * 도면작성은 플랜1번의 도면작성화면으로 이동하기 때문에
- * 1.물건작성하고 바로 -> planList 생성전. surface
- * 2.물건이 여러건있을때 1번 플랜의 estimateDate 여부로 selectedMenu 셋팅
- */
if (managementState?.planList?.length === 0) {
setSelectedMenu('surface')
} else {
@@ -72,6 +70,7 @@ export default function StuffSubHeader({ type }) {
setSelectedMenu('surface')
}
}
+
const url = `/floor-plan?${queryStringFormatter(param)}`
router.push(url)
diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js
index 089aeea9..19736e81 100644
--- a/src/hooks/common/useCanvasConfigInitialize.js
+++ b/src/hooks/common/useCanvasConfigInitialize.js
@@ -23,7 +23,7 @@ export function useCanvasConfigInitialize() {
const {} = useFont()
const {} = useGrid()
const {} = useRoof()
- const { drawDirectionArrow } = usePolygon()
+ const { drawDirectionArrow, addLengthText } = usePolygon()
useEffect(() => {
if (!canvas) return
@@ -160,11 +160,15 @@ export function useCanvasConfigInitialize() {
const objectsParentId = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)[0].parentId
let objectArray = []
+ let groupPoints = []
//그룹객체가 있으면 배열에 추가함
if (groupObjects) {
groupObjects.forEach((obj) => {
objectArray.push(obj)
+ if (obj.groupPoints) {
+ groupPoints = obj.groupPoints
+ }
})
}
@@ -187,9 +191,21 @@ export function useCanvasConfigInitialize() {
})
canvas.add(group)
+ //도머등 그룹에 포인트가 있는애들한테 다시 넣어준다
+ if (groupPoints.length > 0) {
+ group.set({
+ groupPoints: groupPoints,
+ })
+ }
+
//그룹 객체 재그룹 완료
group.getObjects().forEach((obj) => {
obj.fire('modified')
+ if (obj.texts) {
+ obj.texts.forEach((text) => {
+ text.bringToFront()
+ })
+ }
})
})
}
diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js
index 8ecb912b..d5c1bd01 100644
--- a/src/hooks/common/useCommonUtils.js
+++ b/src/hooks/common/useCommonUtils.js
@@ -10,6 +10,8 @@ import { v4 as uuidv4 } from 'uuid'
import { usePopup } from '@/hooks/usePopup'
import Distance from '@/components/floor-plan/modal/distance/Distance'
import { usePolygon } from '@/hooks/usePolygon'
+import { useObjectBatch } from '@/hooks/object/useObjectBatch'
+import { BATCH_TYPE } from '@/common/common'
export function useCommonUtils() {
const canvas = useRecoilValue(canvasState)
@@ -22,6 +24,7 @@ export function useCommonUtils() {
const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState)
const { addPopup } = usePopup()
const { drawDirectionArrow, addLengthText } = usePolygon()
+ const { applyDormers } = useObjectBatch({})
useEffect(() => {
if (commonUtils.text) {
@@ -558,60 +561,79 @@ export function useCommonUtils() {
const commonCopyObject = (obj) => {
if (obj) {
- let clonedObj = null
+ //도머는 복사하기 보다 새로 호출해서 만드는 방법으로 함
+ if (obj.name == BATCH_TYPE.TRIANGLE_DORMER || obj.name == BATCH_TYPE.PENTAGON_DORMER) {
+ //그룹 객체 0번에 도머 속성을 넣어둠
+ const dormerAttributes = obj._objects[0].dormerAttributes
+ const dormerName = obj._objects[0].name
- obj.clone((cloned) => {
- clonedObj = cloned
- clonedObj.fontSize = lengthTextFont.fontSize.value
- })
-
- addCanvasMouseEventListener('mouse:move', (e) => {
- const pointer = canvas?.getPointer(e.e)
- if (!clonedObj) return
-
- canvas
- .getObjects()
- .filter((obj) => obj.name === 'clonedObj')
- .forEach((obj) => canvas?.remove(obj))
-
- clonedObj.set({
- left: pointer.x,
- top: pointer.y,
- name: 'clonedObj',
- })
- canvas.add(clonedObj)
- })
-
- addCanvasMouseEventListener('mouse:down', (e) => {
- clonedObj.set({
- lockMovementX: true,
- lockMovementY: true,
- name: obj.name,
- editable: false,
- id: uuidv4(), //복사된 객체라 새로 따준다
- })
-
- //객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다
- if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() })
-
- //배치면일 경우
- if (obj.name === 'roof') {
- clonedObj.setCoords()
- clonedObj.fire('modified')
- clonedObj.fire('polygonMoved')
- clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial })
-
- obj.lines.forEach((line, index) => {
- clonedObj.lines[index].set({ attributes: line.attributes })
- })
-
- canvas.renderAll()
- addLengthText(clonedObj) //수치 추가
- drawDirectionArrow(clonedObj) //방향 화살표 추가
+ const dormerParams = {
+ height: dormerAttributes.height,
+ width: dormerAttributes.width,
+ pitch: dormerAttributes.pitch,
+ offsetRef: dormerAttributes.offsetRef,
+ offsetWidthRef: dormerAttributes.offsetWidthRef,
+ directionRef: dormerAttributes.directionRef,
}
- initEvent()
- })
+ const buttonAct = dormerName == BATCH_TYPE.TRIANGLE_DORMER ? 3 : 4
+ applyDormers(dormerParams, buttonAct)
+ } else {
+ let clonedObj = null
+
+ obj.clone((cloned) => {
+ clonedObj = cloned
+ clonedObj.fontSize = lengthTextFont.fontSize.value
+ })
+
+ addCanvasMouseEventListener('mouse:move', (e) => {
+ const pointer = canvas?.getPointer(e.e)
+ if (!clonedObj) return
+
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'clonedObj')
+ .forEach((obj) => canvas?.remove(obj))
+
+ clonedObj.set({
+ left: pointer.x,
+ top: pointer.y,
+ name: 'clonedObj',
+ })
+ canvas.add(clonedObj)
+ })
+
+ addCanvasMouseEventListener('mouse:down', (e) => {
+ clonedObj.set({
+ lockMovementX: true,
+ lockMovementY: true,
+ name: obj.name,
+ editable: false,
+ id: uuidv4(), //복사된 객체라 새로 따준다
+ })
+
+ //객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다
+ if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() })
+
+ //배치면일 경우
+ if (obj.name === 'roof') {
+ clonedObj.setCoords()
+ clonedObj.fire('modified')
+ clonedObj.fire('polygonMoved')
+ clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial })
+
+ obj.lines.forEach((line, index) => {
+ clonedObj.lines[index].set({ attributes: line.attributes })
+ })
+
+ canvas.renderAll()
+ addLengthText(clonedObj) //수치 추가
+ drawDirectionArrow(clonedObj) //방향 화살표 추가
+ }
+
+ initEvent()
+ })
+ }
}
}
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js
index 3deee779..37d8dc1d 100644
--- a/src/hooks/module/useModuleBasicSetting.js
+++ b/src/hooks/module/useModuleBasicSetting.js
@@ -391,11 +391,11 @@ export function useModuleBasicSetting(tabNum) {
//모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화
const restoreModuleInstArea = () => {
//설치면 삭제
- const setupArea = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
+ const setupArea = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE || obj.name === POLYGON_TYPE.OBJECT_SURFACE)
//모듈 삭제 및 초기화
setupArea.forEach((obj) => {
- if (obj.modules.length > 0) {
+ if (isObjectNotEmpty(obj.modules) && obj.modules.length > 0) {
obj.modules.forEach((module) => {
canvas.remove(module)
})
@@ -407,7 +407,7 @@ export function useModuleBasicSetting(tabNum) {
//지붕패턴 변경
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
roofs.forEach((roof) => {
- setSurfaceShapePattern(roof, roofDisplay.column, false) //패턴 변경
+ setSurfaceShapePattern(roof, roofDisplay.column, false, roof.roofMaterial) //패턴 변경
})
}
diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js
index 231f422c..de4671dc 100644
--- a/src/hooks/object/useObjectBatch.js
+++ b/src/hooks/object/useObjectBatch.js
@@ -1,11 +1,18 @@
'use client'
-import { useEffect } from 'react'
+import { useEffect, useRef } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { BATCH_TYPE, INPUT_TYPE, POLYGON_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent'
-import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon } from '@/util/canvas-util'
+import {
+ pointsToTurfPolygon,
+ polygonToTurfPolygon,
+ rectToPolygon,
+ triangleToPolygon,
+ getDegreeByChon,
+ toFixedWithoutRounding,
+} from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal'
import * as turf from '@turf/turf'
import { usePolygon } from '@/hooks/usePolygon'
@@ -13,6 +20,7 @@ import { QPolygon } from '@/components/fabric/QPolygon'
import { v4 as uuidv4 } from 'uuid'
import { fontSelector } from '@/store/fontAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
+import { roofDisplaySelector } from '@/store/settingAtom'
export function useObjectBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage()
@@ -23,6 +31,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
const { drawDirectionArrow } = usePolygon()
const { setSurfaceShapePattern } = useRoofFn()
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
+ const roofDisplay = useRecoilValue(roofDisplaySelector)
+
+ const { addPolygon } = usePolygon()
useEffect(() => {
if (canvas) {
@@ -71,13 +82,15 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
}
}
- const applyOpeningAndShadow = (objectPlacement, buttonAct, surfaceShapePolygons) => {
+ const applyOpeningAndShadow = (objectPlacement, buttonAct) => {
const selectedType = objectPlacement.typeRef.current.find((radio) => radio.checked).value
const isCrossChecked = buttonAct === 1 ? objectPlacement.isCrossRef.current.checked : false
const objName = buttonAct === 1 ? BATCH_TYPE.OPENING : BATCH_TYPE.SHADOW
+ const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
const objTempName = buttonAct === 1 ? BATCH_TYPE.OPENING_TEMP : BATCH_TYPE.SHADOW_TEMP
let rect, isDown, origX, origY
+
let selectedSurface
//프리입력
@@ -267,26 +280,17 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
* @param {*} surfaceShapePolygons
* @returns
*/
- const applyDormers = (dormerPlacement, buttonAct, surfaceShapePolygons) => {
+ const applyDormers = ({ height, width, pitch, offsetRef, offsetWidthRef, directionRef }, buttonAct) => {
const dormerName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER : BATCH_TYPE.PENTAGON_DORMER
const dormerTempName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER_TEMP : BATCH_TYPE.PENTAGON_DORMER_TEMP
- const height = dormerPlacement.heightRef.current !== null ? dormerPlacement.heightRef.current.value / 10 : 0
- const width = dormerPlacement.widthRef.current !== null ? dormerPlacement.widthRef.current.value / 10 : 0 //triangle일때는 없음
- const pitch = dormerPlacement.pitchRef.current !== null ? dormerPlacement.pitchRef.current.value : 0
- const offsetRef =
- dormerPlacement.offsetRef.current !== null
- ? dormerPlacement.offsetRef.current.value === ''
- ? 0
- : parseInt(dormerPlacement.offsetRef.current.value) / 10
- : 0
- const offsetWidthRef =
- dormerPlacement.offsetWidthRef.current !== null
- ? dormerPlacement.offsetWidthRef.current.value === ''
- ? 0
- : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10
- : 0
- const directionRef = dormerPlacement.directionRef.current
+
+ //도머의 각도
+ const dormerAngle = getDegreeByChon(pitch)
+
let dormer, dormerOffset, isDown, selectedSurface, pentagonPoints, pentagonOffsetPoints
+
+ const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
+
const id = uuidv4()
if (height === '' || pitch === '' || height <= 0 || pitch <= 0) {
@@ -294,12 +298,21 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
return
}
+ let theta = 0
+
//삼각형 도머
if (buttonAct === 3) {
- const bottomLength = height / (pitch * 0.25)
- const bottomOffsetLength = (height + offsetRef) / (pitch * 0.25)
let groupDormerPoints = [] //나중에 offset을 위한 포인트 저장용
+ let bottomLength = 0,
+ bottomOffsetLength = 0,
+ planeHypotenuse = 0,
+ planeOffsetHypotenuse = 0,
+ actualBottomLength = 0,
+ actualBottomOffsetLength = 0,
+ actualHypotenuse = 0,
+ actualOffsetHypotenuse = 0
+
addCanvasMouseEventListener('mouse:move', (e) => {
isDown = true
if (!isDown) return
@@ -313,48 +326,51 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
}
})
- let angle = 0
- if (directionRef === 'left') {
- //서
- angle = 90
- } else if (directionRef === 'right') {
- //동
- angle = 270
- } else if (directionRef === 'up') {
- //북
- angle = 180
- }
+ if (selectedSurface) {
+ const roofAngle = selectedSurface.roofMaterial.angle
- dormer = new fabric.Triangle({
- fill: 'white',
- stroke: 'red',
- strokeDashArray: [5, 5],
- strokeWidth: 1,
- width: bottomLength * 2,
- height: height,
- left: pointer.x,
- top: pointer.y,
- selectable: true,
- lockMovementX: true,
- lockMovementY: true,
- lockRotation: true,
- lockScalingX: true,
- lockScalingY: true,
- name: dormerTempName,
- originX: 'center',
- originY: 'top',
- angle: angle,
- })
- canvas?.add(dormer)
+ theta = Math.atan(Math.tan((roofAngle * Math.PI) / 180) / Math.tan((dormerAngle * Math.PI) / 180))
- if (offsetRef > 0) {
- dormerOffset = new fabric.Triangle({
- fill: 'gray',
+ //센터 삼각형용
+ bottomLength = Number((Math.tan(theta) * height).toFixed())
+
+ //좌우 삼각형용
+ bottomOffsetLength = Number((Math.tan(theta) * (height + offsetRef)).toFixed())
+
+ planeHypotenuse = Math.sqrt(Math.pow(height, 2) + Math.pow(bottomLength, 2))
+
+ actualBottomLength = Math.sqrt(
+ Math.pow(Math.tan(theta) * height, 2) + Math.pow(Math.tan(theta) * height * Math.tan((dormerAngle * Math.PI) / 180), 2),
+ )
+ actualHypotenuse = Math.sqrt(Math.pow(height, 2) + Math.pow(actualBottomLength, 2))
+
+ actualBottomOffsetLength = Math.sqrt(
+ Math.pow(Math.tan(theta) * (height + offsetRef), 2) +
+ Math.pow(Math.tan(theta) * (height + offsetRef) * Math.tan((dormerAngle * Math.PI) / 180), 2),
+ )
+
+ planeOffsetHypotenuse = Math.sqrt(Math.pow(height + offsetRef, 2) + Math.pow(bottomOffsetLength, 2))
+ actualOffsetHypotenuse = Math.sqrt(Math.pow(height + offsetRef, 2) + Math.pow(actualBottomOffsetLength, 2))
+
+ let angle = 0
+ if (directionRef === 'left') {
+ //서
+ angle = 90
+ } else if (directionRef === 'right') {
+ //동
+ angle = 270
+ } else if (directionRef === 'up') {
+ //북
+ angle = 180
+ }
+
+ dormer = new fabric.Triangle({
+ fill: 'white',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
- width: bottomOffsetLength * 2,
- height: height + offsetRef,
+ width: bottomLength * 2,
+ height: height,
left: pointer.x,
top: pointer.y,
selectable: true,
@@ -367,9 +383,33 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
originX: 'center',
originY: 'top',
angle: angle,
- objectId: id,
})
- canvas?.add(dormerOffset)
+ canvas?.add(dormer)
+
+ if (offsetRef > 0) {
+ dormerOffset = new fabric.Triangle({
+ fill: 'gray',
+ stroke: 'red',
+ strokeDashArray: [5, 5],
+ strokeWidth: 1,
+ width: bottomOffsetLength * 2,
+ height: height + offsetRef,
+ left: pointer.x,
+ top: pointer.y,
+ selectable: true,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ name: dormerTempName,
+ originX: 'center',
+ originY: 'top',
+ angle: angle,
+ objectId: id,
+ })
+ canvas?.add(dormerOffset)
+ }
}
})
@@ -416,50 +456,120 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
strokeDashArray: [0],
}) //오프셋이 있을땐 같이 도머로 만든다
- const leftTriangle = new QPolygon(leftPoints, {
- fill: 'white',
- stroke: 'black',
- strokeWidth: 1,
- selectable: true,
- lockMovementX: true, // X 축 이동 잠금
- lockMovementY: true, // Y 축 이동 잠금
- lockRotation: true, // 회전 잠금
- viewLengthText: true,
- // direction: direction,
- originX: 'center',
- originY: 'center',
- name: dormerName,
- pitch: pitch,
- fontSize: lengthTextFont.fontSize.value,
- fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
- fontWeight: lengthTextFont.fontWeight.value,
+ const leftTriangle = addPolygon(
+ leftPoints,
+ {
+ fill: 'white',
+ stroke: 'black',
+ strokeWidth: 1,
+ selectable: true,
+ lockMovementX: true, // X 축 이동 잠금
+ lockMovementY: true, // Y 축 이동 잠금
+ lockRotation: true, // 회전 잠금
+ viewLengthText: true,
+ // direction: direction,
+ originX: 'center',
+ originY: 'center',
+ name: dormerName,
+ pitch: pitch,
+ fontSize: lengthTextFont.fontSize.value,
+ fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
+ fontWeight: lengthTextFont.fontWeight.value,
+ groupPoints: groupPoints,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
+ lines: [
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(planeOffsetHypotenuse, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualOffsetHypotenuse, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(bottomOffsetLength, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualBottomOffsetLength, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
+ actualSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
+ },
+ },
+ ],
+ },
+ false,
+ )
+
+ leftTriangle.texts.forEach((text) => {
+ text.bringToFront()
})
- const rightTriangle = new QPolygon(rightPoints, {
- fill: 'white',
- stroke: 'black',
- strokeWidth: 1,
- selectable: true,
- lockMovementX: true, // X 축 이동 잠금
- lockMovementY: true, // Y 축 이동 잠금
- lockRotation: true, // 회전 잠금
- viewLengthText: true,
- // direction: direction,
- originX: 'center',
- originY: 'center',
- name: dormerName,
- pitch: pitch,
- fontSize: lengthTextFont.fontSize.value,
- fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
- fontWeight: lengthTextFont.fontWeight.value,
- })
+ const rightTriangle = addPolygon(
+ rightPoints,
+ {
+ fill: 'white',
+ stroke: 'black',
+ strokeWidth: 1,
+ selectable: true,
+ lockMovementX: true, // X 축 이동 잠금
+ lockMovementY: true, // Y 축 이동 잠금
+ lockRotation: true, // 회전 잠금
+ viewLengthText: true,
+ // direction: direction,
+ originX: 'center',
+ originY: 'center',
+ name: dormerName,
+ pitch: pitch,
+ fontSize: lengthTextFont.fontSize.value,
+ fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
+ fontWeight: lengthTextFont.fontWeight.value,
+ groupPoints: groupPoints,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
+ lines: [
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
+ actualSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(bottomOffsetLength, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualBottomOffsetLength, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(planeOffsetHypotenuse, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualOffsetHypotenuse, 1) * 10,
+ },
+ },
+ ],
+ },
+ false,
+ )
// canvas?.add(leftTriangle)
// canvas?.add(rightTriangle)
//패턴
- setSurfaceShapePattern(leftTriangle)
- setSurfaceShapePattern(rightTriangle)
+ setSurfaceShapePattern(leftTriangle, roofDisplay.column, false, selectedSurface.roofMaterial, true)
+ setSurfaceShapePattern(rightTriangle, roofDisplay.column, false, selectedSurface.roofMaterial, true)
//방향
// drawDirectionArrow(leftTriangle)
@@ -472,24 +582,57 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
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: 'top',
- fontSize: lengthTextFont.fontSize.value,
- fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
- fontWeight: lengthTextFont.fontWeight.value,
- angle: originAngle,
- })
+ offsetPolygon = addPolygon(
+ 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: 'top',
+ fontSize: lengthTextFont.fontSize.value,
+ fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
+ fontWeight: lengthTextFont.fontWeight.value,
+ angle: originAngle,
+ pitch: pitch,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
+ lines: [
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(planeHypotenuse, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualHypotenuse, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(bottomLength * 2, 1) * 10,
+ actualSize: toFixedWithoutRounding(bottomLength * 2, 1) * 10,
+ },
+ },
+ {
+ attributes: {
+ planeSize: toFixedWithoutRounding(planeHypotenuse, 1) * 10,
+ actualSize: toFixedWithoutRounding(actualHypotenuse, 1) * 10,
+ },
+ },
+ ],
+ },
+ false,
+ )
}
const groupPolygon = offsetPolygon ? [leftTriangle, rightTriangle, offsetPolygon] : [leftTriangle, rightTriangle]
@@ -505,10 +648,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
})
canvas?.add(objectGroup)
- objectGroup.getObjects().forEach((obj, index) => {
- console.log(`최초 pathOffset ${index}`, obj.get('pathOffset'))
- })
-
objectGroup._objects.forEach((obj) => {
if (obj.hasOwnProperty('texts')) {
obj.texts.forEach((text) => {
@@ -519,7 +658,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
isDown = false
initEvent()
- dbClickEvent()
+ // dbClickEvent()
if (setIsHidden) setIsHidden(false)
}
})
@@ -528,8 +667,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
//(동의길이 깊이)+출폭(깊이)-[(입력한 폭값)/2+출폭(폭)]*(0.25*입력한 寸)
const heightOffsetLength = height + offsetRef - (width / 2 + offsetWidthRef) * (pitch * 0.25)
- let groupDormerPoints = []
-
addCanvasMouseEventListener('mouse:move', (e) => {
isDown = true
if (!isDown) return
@@ -672,6 +809,15 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
originY: 'center',
name: dormerName,
pitch: pitch,
+ groupPoints: groupPoints,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
})
const rightPentagon = new QPolygon(rightPoints, {
@@ -689,6 +835,15 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
originY: 'center',
name: dormerName,
pitch: pitch,
+ groupPoints: groupPoints,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
})
// canvas?.add(leftPentagon)
@@ -703,8 +858,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
let offsetPolygon
- groupDormerPoints = groupPoints
-
if (offsetRef > 0) {
canvas?.remove(dormer)
@@ -725,6 +878,15 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
angle: originAngle,
+ groupPoints: groupPoints,
+ dormerAttributes: {
+ height: height,
+ width: width,
+ pitch: pitch,
+ offsetRef: offsetRef,
+ offsetWidthRef: offsetWidthRef,
+ directionRef: directionRef,
+ },
})
}
@@ -738,7 +900,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
groupYn: true,
originX: 'center',
originY: 'center',
- groupPoints: groupDormerPoints,
+ groupPoints: groupPoints,
})
canvas?.add(objectGroup)
@@ -753,7 +915,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
isDown = false
initEvent()
- dbClickEvent()
+ // dbClickEvent()
}
})
}
@@ -1191,6 +1353,26 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
}
}
+ const dormerPlacement = {
+ widthRef: useRef(null),
+ heightRef: useRef(null),
+ pitchRef: useRef(null),
+ offsetRef: useRef(null),
+ offsetWidthRef: useRef(null),
+ directionRef: useRef(null),
+ }
+
+ const copyOjbectDormer = () => {
+ const obj = canvas.getActiveObject()
+ if (obj) {
+ if (obj.name === 'triangleDormer') {
+ const offset = obj._objects.filter((item) => item.name === 'triangleDormerOffset')
+ } else {
+ //오각도머
+ }
+ }
+ }
+
const dormerOffsetKeyEvent = (setArrow1, setArrow2) => {
addDocumentEventListener('keydown', document, (e) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js
index ed7b2ca1..2bfcde38 100644
--- a/src/hooks/surface/useSurfaceShapeBatch.js
+++ b/src/hooks/surface/useSurfaceShapeBatch.js
@@ -26,7 +26,7 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage()
- const { drawDirectionArrow } = usePolygon()
+ const { drawDirectionArrow, addPolygon } = usePolygon()
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
@@ -178,10 +178,10 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
}
//회전, flip등이 먹은 기준으로 새로생성
- const batchSurface = new QPolygon(obj.getCurrentPoints(), {
+ const batchSurface = addPolygon(obj.getCurrentPoints(), {
fill: 'transparent',
stroke: 'red',
- strokeWidth: 1,
+ strokeWidth: 3,
strokeDasharray: [10, 4],
fontSize: 12,
selectable: true,
diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js
index 04507c17..54de877b 100644
--- a/src/hooks/usePolygon.js
+++ b/src/hooks/usePolygon.js
@@ -17,16 +17,16 @@ export const usePolygon = () => {
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
- const addPolygon = (points, options) => {
+ const addPolygon = (points, options, isAddCanvas = true) => {
const polygon = new QPolygon(points, {
...options,
fontSize: lengthTextFontOptions.fontSize.value,
fill: options.fill || 'transparent',
stroke: options.stroke || '#000000',
- selectable: true,
+ // selectable: true,
})
- canvas?.add(polygon)
+ if (isAddCanvas) canvas?.add(polygon)
addLengthText(polygon)
return polygon
@@ -48,6 +48,7 @@ export const usePolygon = () => {
canvas.remove(text)
})
const lines = polygon.lines
+ polygon.texts = []
lines.forEach((line, i) => {
const length = line.getLength()
@@ -102,7 +103,7 @@ export const usePolygon = () => {
parent: polygon,
name: 'lengthText',
})
-
+ polygon.texts.push(text)
canvas.add(text)
})
diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js
index 83f604ec..66116af8 100644
--- a/src/util/canvas-util.js
+++ b/src/util/canvas-util.js
@@ -1035,3 +1035,8 @@ export function calculateVisibleModuleHeight(sourceWidth, sourceHeight, angle, d
height: Number(visibleHeight.toFixed(1)), // 소수점 두 자리로 고정
}
}
+
+//숫자, 몇자리수
+export function toFixedWithoutRounding(number, decimals) {
+ return Math.floor(number * Math.pow(10, decimals)) / Math.pow(10, decimals)
+}