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