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