Merge branch 'feature/test' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into feature/hj
# Conflicts: # src/hooks/useMode.js
This commit is contained in:
commit
933f2a67c4
@ -1,10 +1,10 @@
|
|||||||
import { useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import QRect from '@/components/fabric/QRect'
|
import QRect from '@/components/fabric/QRect'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
import QPolygon from '@/components/fabric/QPolygon'
|
||||||
import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util'
|
import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
|
|
||||||
import { fontSizeState, roofState, sortedPolygonArray, roofPolygonPatternArrayState, wallState } from '@/store/canvasAtom'
|
import { fontSizeState, roofPolygonPatternArrayState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
export const Mode = {
|
export const Mode = {
|
||||||
@ -34,6 +34,19 @@ export function useMode() {
|
|||||||
|
|
||||||
const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
|
const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 이벤트 리스너 추가
|
||||||
|
if (!canvas) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
|
|
||||||
|
// 컴포넌트가 언마운트될 때 이벤트 리스너 제거
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('keydown', handleKeyDown)
|
||||||
|
}
|
||||||
|
}, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함
|
||||||
|
|
||||||
const addEvent = (mode) => {
|
const addEvent = (mode) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'default':
|
case 'default':
|
||||||
@ -66,6 +79,131 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyValid = () => {
|
||||||
|
if (points.current.length === 0) {
|
||||||
|
alert('시작점을 선택해주세요')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawCircleAndLine = (verticalLength, horizontalLength) => {
|
||||||
|
const circle = new fabric.Circle({
|
||||||
|
radius: 5,
|
||||||
|
fill: 'transparent', // 원 안을 비웁니다.
|
||||||
|
stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||||
|
left: points.current[points.current.length - 1].left + horizontalLength - 5,
|
||||||
|
top: points.current[points.current.length - 1].top + verticalLength - 5,
|
||||||
|
originX: 'center',
|
||||||
|
originY: 'center',
|
||||||
|
selectable: false,
|
||||||
|
})
|
||||||
|
historyPoints.current.push(circle)
|
||||||
|
points.current.push(circle)
|
||||||
|
canvas?.add(circle)
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
|
// length 값이 숫자가 아닌 경우
|
||||||
|
if (isNaN(length) || Math.max(Math.abs(verticalLength), Math.abs(horizontalLength)) === 0) {
|
||||||
|
//마지막 추가 된 points 제거합니다.
|
||||||
|
|
||||||
|
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||||
|
|
||||||
|
canvas?.remove(lastPoint)
|
||||||
|
|
||||||
|
historyPoints.current.pop()
|
||||||
|
points.current.pop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const line = new QLine(
|
||||||
|
[points.current[0].left, points.current[0].top, points.current[0].left + horizontalLength, points.current[0].top + verticalLength],
|
||||||
|
{
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
viewLengthText: true,
|
||||||
|
direction: getDirection(points.current[0], points.current[1]),
|
||||||
|
fontSize: fontSize,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pushHistoryLine(line)
|
||||||
|
|
||||||
|
// 라인의 끝에 점을 추가합니다.
|
||||||
|
const endPointCircle = new fabric.Circle({
|
||||||
|
radius: 1,
|
||||||
|
fill: 'transparent', // 원 안을 비웁니다.
|
||||||
|
stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||||
|
left: points.current[0].left + horizontalLength,
|
||||||
|
top: points.current[0].top + verticalLength,
|
||||||
|
originX: 'center',
|
||||||
|
originY: 'center',
|
||||||
|
selectable: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(endPointCircle)
|
||||||
|
|
||||||
|
historyPoints.current.push(endPointCircle)
|
||||||
|
|
||||||
|
points.current.forEach((point) => {
|
||||||
|
canvas?.remove(point)
|
||||||
|
})
|
||||||
|
points.current = [endPointCircle]
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyDown = (e) => {
|
||||||
|
switch (e.key) {
|
||||||
|
case 'ArrowDown': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = Number(prompt('길이를 입력하세요:'))
|
||||||
|
const horizontalLength = 0
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'ArrowUp': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = -Number(prompt('길이를 입력하세요:'))
|
||||||
|
const horizontalLength = 0
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'ArrowLeft': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = 0
|
||||||
|
const horizontalLength = -Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'ArrowRight': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const verticalLength = 0
|
||||||
|
const horizontalLength = Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const changeMode = (canvas, mode) => {
|
const changeMode = (canvas, mode) => {
|
||||||
setMode(mode)
|
setMode(mode)
|
||||||
// mode변경 시 이전 이벤트 제거
|
// mode변경 시 이전 이벤트 제거
|
||||||
|
|||||||
@ -426,9 +426,58 @@ export function findOrthogonalPoint(line1, line2) {
|
|||||||
export const sortedPoints = (points) => {
|
export const sortedPoints = (points) => {
|
||||||
const copyPoints = [...points]
|
const copyPoints = [...points]
|
||||||
//points를 x,y좌표를 기준으로 정렬합니다.
|
//points를 x,y좌표를 기준으로 정렬합니다.
|
||||||
|
copyPoints.sort((a, b) => {
|
||||||
|
if (a.x === b.x) {
|
||||||
|
return a.y - b.y
|
||||||
|
}
|
||||||
|
return a.x - b.x
|
||||||
|
})
|
||||||
|
|
||||||
const idx = getStartIndexPoint(copyPoints)
|
// 이때 copyPoints를 순회하며 최초엔 x값을 비교하여 같은 점을 찾는다. 이때 이 점이 2번째 점이 된다.
|
||||||
return rearrangeArray(copyPoints, idx)
|
// 그 다음점은 2번째 점과 y값이 같은 점이 된다.
|
||||||
|
// 또 그다음 점은 3번째 점과 x값이 같은 점이 된다.
|
||||||
|
// 이를 반복하여 copyPoints를 재배열한다.
|
||||||
|
const resultPoints = [copyPoints[0]]
|
||||||
|
let index = 1
|
||||||
|
let currentPoint = { ...copyPoints[0] }
|
||||||
|
copyPoints.splice(0, 1)
|
||||||
|
while (index < points.length) {
|
||||||
|
if (index === points.length - 1) {
|
||||||
|
resultPoints.push(copyPoints[0])
|
||||||
|
index++
|
||||||
|
break
|
||||||
|
} else if (index % 2 === 0) {
|
||||||
|
// 짝수번째는 y값이 같은 점을 찾는다.
|
||||||
|
for (let i = 0; i < copyPoints.length; i++) {
|
||||||
|
// y값이 같은 point가 많은 경우 그 중 x값이 가장 큰걸 찾는다.
|
||||||
|
const temp = copyPoints.filter((point) => point.y === currentPoint.y)
|
||||||
|
// temp중 x값이 가장 가까운 값
|
||||||
|
|
||||||
|
const min = temp.reduce((prev, current) => (Math.abs(current.x - currentPoint.x) <= Math.abs(prev.x - currentPoint.x) ? current : prev))
|
||||||
|
|
||||||
|
resultPoints.push(min)
|
||||||
|
currentPoint = min
|
||||||
|
copyPoints.splice(copyPoints.indexOf(min), 1)
|
||||||
|
index++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 홀수번째는 x값이 같은 점을 찾는다.
|
||||||
|
for (let i = 0; i < copyPoints.length; i++) {
|
||||||
|
// x값이 같은 point가 많은 경우 그 중 y값이 가장 큰걸 찾는다.
|
||||||
|
const temp = copyPoints.filter((point) => point.x === currentPoint.x)
|
||||||
|
// temp중 y값이 가장 가까운 값
|
||||||
|
const min = temp.reduce((prev, current) => (Math.abs(current.y - currentPoint.y) <= Math.abs(prev.y - currentPoint.y) ? current : prev))
|
||||||
|
|
||||||
|
resultPoints.push(min)
|
||||||
|
currentPoint = min
|
||||||
|
copyPoints.splice(copyPoints.indexOf(min), 1)
|
||||||
|
index++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user