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