이벤트 분리
This commit is contained in:
parent
bc77a9725e
commit
5cf29ec019
@ -425,6 +425,8 @@ export function useCanvas(id) {
|
|||||||
'maxY',
|
'maxY',
|
||||||
'minX',
|
'minX',
|
||||||
'minY',
|
'minY',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
])
|
])
|
||||||
|
|
||||||
const str = JSON.stringify(objs)
|
const str = JSON.stringify(objs)
|
||||||
|
|||||||
@ -19,9 +19,9 @@ export function useCanvasEvent() {
|
|||||||
canvas?.on('selection:cleared', selectionEvent.cleared)
|
canvas?.on('selection:cleared', selectionEvent.cleared)
|
||||||
canvas?.on('selection:created', selectionEvent.created)
|
canvas?.on('selection:created', selectionEvent.created)
|
||||||
canvas?.on('selection:updated', selectionEvent.updated)
|
canvas?.on('selection:updated', selectionEvent.updated)
|
||||||
canvas?.on('object:added', () => {
|
/*canvas?.on('object:added', () => {
|
||||||
document.addEventListener('keydown', handleKeyDown)
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
})
|
})*/
|
||||||
canvas?.on('object:removed', objectEvent.removed)
|
canvas?.on('object:removed', objectEvent.removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
calculateIntersection,
|
calculateIntersection,
|
||||||
distanceBetweenPoints,
|
distanceBetweenPoints,
|
||||||
@ -64,23 +64,22 @@ export function useMode() {
|
|||||||
const compass = useRecoilValue(compassState)
|
const compass = useRecoilValue(compassState)
|
||||||
const [isCellCenter, setIsCellCenter] = useState(false)
|
const [isCellCenter, setIsCellCenter] = useState(false)
|
||||||
|
|
||||||
const guideLineInfo = useRecoilValue(guideLineState)
|
const [guideLineInfo, setGuideLineInfo] = useRecoilState(guideLineState)
|
||||||
|
|
||||||
const [guideLineMode, setGuideLineMode] = useState(false)
|
const [guideLineMode, setGuideLineMode] = useState(false)
|
||||||
const [guideDotMode, setGuideDotMode] = useState(false)
|
const [guideDotMode, setGuideDotMode] = useState(false)
|
||||||
|
|
||||||
|
const [horiGuideLines, setHoriGuideLines] = useState([])
|
||||||
|
const [vertGuideLines, setVertGuideLines] = useState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 이벤트 리스너 추가
|
|
||||||
// if (!canvas) {
|
// if (!canvas) {
|
||||||
// canvas?.setZoom(0.8)
|
// canvas?.setZoom(0.8)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
document.addEventListener('keydown', handleKeyDown)
|
if (!canvas) return
|
||||||
|
setCanvas(canvas)
|
||||||
canvas?.on('mouse:move', drawMouseLines)
|
canvas?.on('mouse:move', drawMouseLines)
|
||||||
// 컴포넌트가 언마운트될 때 이벤트 리스너 제거
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('keydown', handleKeyDown)
|
|
||||||
}
|
|
||||||
}, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함
|
}, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -103,11 +102,6 @@ export function useMode() {
|
|||||||
canvas?.off('mouse:move')
|
canvas?.off('mouse:move')
|
||||||
canvas?.on('mouse:move', drawMouseLines)
|
canvas?.on('mouse:move', drawMouseLines)
|
||||||
changeMode(canvas, mode)
|
changeMode(canvas, mode)
|
||||||
/*
|
|
||||||
if (mode === Mode.EDIT) {
|
|
||||||
canvas?.off('mouse:down')
|
|
||||||
canvas?.on('mouse:down', mouseEvent.editMode)
|
|
||||||
}*/
|
|
||||||
}, [mode])
|
}, [mode])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -117,6 +111,9 @@ export function useMode() {
|
|||||||
const guideLineState = guideLineInfo.filter((item) => item.guideMode === 'guideLine')
|
const guideLineState = guideLineInfo.filter((item) => item.guideMode === 'guideLine')
|
||||||
const guideDotState = guideLineInfo.filter((item) => item.guideMode === 'guideDot')
|
const guideDotState = guideLineInfo.filter((item) => item.guideMode === 'guideDot')
|
||||||
|
|
||||||
|
setHoriGuideLines(guideLineState[0].horizontalLineArray)
|
||||||
|
setVertGuideLines(guideLineState[0].verticalLineArray)
|
||||||
|
|
||||||
setGuideLineMode(guideLineState.length > 0)
|
setGuideLineMode(guideLineState.length > 0)
|
||||||
setGuideDotMode(guideDotState.length > 0)
|
setGuideDotMode(guideDotState.length > 0)
|
||||||
}
|
}
|
||||||
@ -142,8 +139,8 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isGuideLineMode) {
|
if (isGuideLineMode) {
|
||||||
horizontalLineArray = [...guideLineState[0].horizontalLineArray]
|
horizontalLineArray = [...horiGuideLines]
|
||||||
verticalLineArray = [...guideLineState[0].verticalLineArray]
|
verticalLineArray = [...vertGuideLines]
|
||||||
guideLineLengthHori = Number(guideLineState[0].moduleHoriLength)
|
guideLineLengthHori = Number(guideLineState[0].moduleHoriLength)
|
||||||
guideLineLengthVert = Number(guideLineState[0].moduleVertLength)
|
guideLineLengthVert = Number(guideLineState[0].moduleVertLength)
|
||||||
}
|
}
|
||||||
@ -163,7 +160,6 @@ export function useMode() {
|
|||||||
|
|
||||||
if (mode === Mode.EDIT || mode === Mode.ADSORPTION_POINT) {
|
if (mode === Mode.EDIT || mode === Mode.ADSORPTION_POINT) {
|
||||||
let adsorptionPoint = adsorptionPointList.length > 0 ? findClosestPoint(pointer, adsorptionPointList) : null
|
let adsorptionPoint = adsorptionPointList.length > 0 ? findClosestPoint(pointer, adsorptionPointList) : null
|
||||||
|
|
||||||
if (isGuideLineMode && isGuideDotMode) {
|
if (isGuideLineMode && isGuideDotMode) {
|
||||||
const closestHorizontalLine = getClosestHorizontalLine(pointer, horizontalLineArray)
|
const closestHorizontalLine = getClosestHorizontalLine(pointer, horizontalLineArray)
|
||||||
const closetVerticalLine = getClosestVerticalLine(pointer, verticalLineArray)
|
const closetVerticalLine = getClosestVerticalLine(pointer, verticalLineArray)
|
||||||
@ -362,12 +358,12 @@ export function useMode() {
|
|||||||
|
|
||||||
// 모드에 따른 마우스 이벤트 변경
|
// 모드에 따른 마우스 이벤트 변경
|
||||||
const changeMouseEvent = (mode) => {
|
const changeMouseEvent = (mode) => {
|
||||||
canvas?.off('mouse:down')
|
document.removeEventListener('contextmenu', mouseEvent.drawLineModeRightClick)
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'drawLine':
|
case 'drawLine':
|
||||||
canvas?.on('mouse:down', mouseEvent.drawLineModeLeftClick)
|
canvas?.on('mouse:down', mouseEvent.drawLineModeLeftClick)
|
||||||
window.document.removeEventListener('contextmenu', mouseEvent.drawLineModeRightClick)
|
document.addEventListener('contextmenu', mouseEvent.drawLineModeRightClick)
|
||||||
window.document.addEventListener('contextmenu', mouseEvent.drawLineModeRightClick)
|
|
||||||
break
|
break
|
||||||
case 'edit':
|
case 'edit':
|
||||||
canvas?.on('mouse:down', mouseEvent.editMode)
|
canvas?.on('mouse:down', mouseEvent.editMode)
|
||||||
@ -394,9 +390,6 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 모드에 따른 키보드 이벤트 변경
|
|
||||||
const changeKeyboardEvent = (mode) => {}
|
|
||||||
|
|
||||||
const keyValid = () => {
|
const keyValid = () => {
|
||||||
if (points.current.length === 0) {
|
if (points.current.length === 0) {
|
||||||
alert('시작점을 선택해주세요')
|
alert('시작점을 선택해주세요')
|
||||||
@ -552,70 +545,85 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyDown = (e) => {
|
const mouseAndkeyboardEventClear = () => {
|
||||||
switch (e.key) {
|
Object.keys(mouseEvent).forEach((key) => {
|
||||||
case 'ArrowDown': {
|
canvas?.off('mouse:down', mouseEvent[key])
|
||||||
if (!keyValid()) {
|
})
|
||||||
return
|
Object.keys(keyboardEvent).forEach((key) => {
|
||||||
}
|
window.removeEventListener('keydown', keyboardEvent[key])
|
||||||
const verticalLength = Number(prompt('길이를 입력하세요:'))
|
})
|
||||||
const horizontalLength = 0
|
}
|
||||||
|
|
||||||
drawCircleAndLine(verticalLength, horizontalLength)
|
const keyboardEvent = {
|
||||||
|
// rerendering을 막기 위해 useCallback 사용
|
||||||
|
editMode: useCallback(
|
||||||
|
(e) => {
|
||||||
|
switch (e.key) {
|
||||||
|
case 'ArrowDown': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = Number(prompt('길이를 입력하세요:'))
|
||||||
|
const horizontalLength = 0
|
||||||
|
|
||||||
break
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'Enter': {
|
|
||||||
const result = prompt('입력하세요 (a(A패턴),b(B패턴),t(지붕))')
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case 'a':
|
|
||||||
applyTemplateA()
|
|
||||||
break
|
break
|
||||||
case 'b':
|
}
|
||||||
applyTemplateB()
|
case 'ArrowUp': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = -Number(prompt('길이를 입력하세요:'))
|
||||||
|
const horizontalLength = 0
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
break
|
break
|
||||||
case 't':
|
}
|
||||||
templateMode()
|
case 'ArrowLeft': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const verticalLength = 0
|
||||||
|
const horizontalLength = -Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
case 'ArrowRight': {
|
||||||
|
if (!keyValid()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const verticalLength = 0
|
||||||
|
const horizontalLength = Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'Enter': {
|
||||||
|
const result = prompt('입력하세요 (a(A패턴),b(B패턴),t(지붕))')
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case 'a':
|
||||||
|
applyTemplateA()
|
||||||
|
break
|
||||||
|
case 'b':
|
||||||
|
applyTemplateB()
|
||||||
|
break
|
||||||
|
case 't':
|
||||||
|
templateMode()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
[canvas],
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeMode = (canvas, mode) => {
|
const changeMode = (canvas, mode) => {
|
||||||
@ -623,6 +631,7 @@ export function useMode() {
|
|||||||
setCanvas(canvas)
|
setCanvas(canvas)
|
||||||
|
|
||||||
// mode별 이벤트 변경
|
// mode별 이벤트 변경
|
||||||
|
mouseAndkeyboardEventClear()
|
||||||
changeMouseEvent(mode)
|
changeMouseEvent(mode)
|
||||||
changeKeyboardEvent(mode)
|
changeKeyboardEvent(mode)
|
||||||
|
|
||||||
@ -657,151 +666,184 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const changeKeyboardEvent = (mode) => {
|
||||||
|
if (mode === Mode.EDIT) {
|
||||||
|
switch (mode) {
|
||||||
|
case 'edit':
|
||||||
|
window.addEventListener('keydown', keyboardEvent.editMode)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const mouseEvent = {
|
const mouseEvent = {
|
||||||
drawLineModeLeftClick: (options) => {
|
drawLineModeLeftClick: useCallback(
|
||||||
const pointer = canvas?.getPointer(options.e)
|
(options) => {
|
||||||
|
const pointer = canvas?.getPointer(options.e)
|
||||||
|
|
||||||
const line = new QLine(
|
const line = new QLine(
|
||||||
[pointer.x, 0, pointer.x, canvas.height], // y축에 1자 선을 그립니다.
|
[pointer.x, 0, pointer.x, canvas.height], // y축에 1자 선을 그립니다.
|
||||||
{
|
{
|
||||||
stroke: 'black',
|
stroke: 'gray',
|
||||||
strokeWidth: 2,
|
strokeWidth: 1,
|
||||||
viewLengthText: true,
|
selectable: true,
|
||||||
|
lockMovementX: true,
|
||||||
|
lockMovementY: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
|
name: 'guideLine',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
canvas?.add(line)
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
|
const newVerticalLineArray = [...vertGuideLines, line]
|
||||||
|
setVertGuideLines(newVerticalLineArray)
|
||||||
|
},
|
||||||
|
[canvas, vertGuideLines],
|
||||||
|
),
|
||||||
|
drawLineModeRightClick: useCallback(
|
||||||
|
(options) => {
|
||||||
|
const line = new fabric.Line(
|
||||||
|
[0, options.offsetY, canvasSize.horizontal, options.offsetY], // y축에 1자 선을 그립니다.
|
||||||
|
{
|
||||||
|
stroke: 'gray',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: true,
|
||||||
|
lockMovementX: true,
|
||||||
|
lockMovementY: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
|
name: 'guideLine',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
canvas?.add(line)
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
|
const newHorizontalLineArray = [...horiGuideLines, line]
|
||||||
|
setHoriGuideLines(newHorizontalLineArray)
|
||||||
|
},
|
||||||
|
[canvas, horiGuideLines],
|
||||||
|
),
|
||||||
|
editMode: useCallback(
|
||||||
|
(options) => {
|
||||||
|
let pointer = canvas?.getPointer(options.e)
|
||||||
|
|
||||||
|
if (getInterSectPointByMouseLine()) {
|
||||||
|
pointer = getInterSectPointByMouseLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
const circle = new fabric.Circle({
|
||||||
|
radius: 5,
|
||||||
|
fill: 'transparent', // 원 안을 비웁니다.
|
||||||
|
stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||||
|
left: pointer.x,
|
||||||
|
top: pointer.y,
|
||||||
|
x: pointer.x,
|
||||||
|
y: pointer.y,
|
||||||
|
originX: 'center',
|
||||||
|
originY: 'center',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
fontSize: fontSize,
|
})
|
||||||
},
|
if (!startPoint.current) {
|
||||||
)
|
startPoint.current = circle
|
||||||
|
pointCount.current = pointCount.current + 1
|
||||||
canvas?.add(line)
|
|
||||||
canvas?.renderAll()
|
|
||||||
},
|
|
||||||
drawLineModeRightClick: (options) => {
|
|
||||||
const line = new fabric.Line(
|
|
||||||
[0, options.offsetY, canvas.width, options.offsetY], // y축에 1자 선을 그립니다.
|
|
||||||
{
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 2,
|
|
||||||
viewLengthText: true,
|
|
||||||
selectable: false,
|
|
||||||
fontSize: fontSize,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas?.add(line)
|
|
||||||
canvas?.renderAll()
|
|
||||||
},
|
|
||||||
editMode: (options) => {
|
|
||||||
let pointer = canvas?.getPointer(options.e)
|
|
||||||
|
|
||||||
if (getInterSectPointByMouseLine()) {
|
|
||||||
pointer = getInterSectPointByMouseLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 5,
|
|
||||||
fill: 'transparent', // 원 안을 비웁니다.
|
|
||||||
stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
|
|
||||||
left: pointer.x,
|
|
||||||
top: pointer.y,
|
|
||||||
x: pointer.x,
|
|
||||||
y: pointer.y,
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
selectable: false,
|
|
||||||
})
|
|
||||||
if (!startPoint.current) {
|
|
||||||
startPoint.current = circle
|
|
||||||
pointCount.current = pointCount.current + 1
|
|
||||||
}
|
|
||||||
let prevEndPoint
|
|
||||||
|
|
||||||
setEndPoint((prev) => {
|
|
||||||
prevEndPoint = prev
|
|
||||||
return circle
|
|
||||||
})
|
|
||||||
|
|
||||||
historyPoints.current.push(circle)
|
|
||||||
points.current.push(circle)
|
|
||||||
canvas?.add(circle)
|
|
||||||
|
|
||||||
if (points.current.length === 2) {
|
|
||||||
if (guideLineMode || guideDotMode) {
|
|
||||||
const vector = {
|
|
||||||
x: points.current[1].left - points.current[0].left,
|
|
||||||
y: points.current[1].top - points.current[0].top,
|
|
||||||
}
|
|
||||||
const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
|
||||||
|
|
||||||
let scaledVector
|
|
||||||
|
|
||||||
if (slope >= 1) {
|
|
||||||
// 기울기가 1 이상이면 x축 방향으로 그림
|
|
||||||
scaledVector = {
|
|
||||||
x: 0,
|
|
||||||
y: pointer.y - prevEndPoint?.top,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 기울기가 1 미만이면 y축 방향으로 그림
|
|
||||||
scaledVector = {
|
|
||||||
x: pointer.x - prevEndPoint?.left,
|
|
||||||
y: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const verticalLength = scaledVector.y
|
|
||||||
const horizontalLength = scaledVector.x
|
|
||||||
|
|
||||||
drawCircleAndLine(verticalLength, horizontalLength)
|
|
||||||
canvas?.renderAll()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
const length = Number(prompt('길이를 입력하세요:'))
|
let prevEndPoint
|
||||||
|
|
||||||
// length 값이 숫자가 아닌 경우
|
setEndPoint((prev) => {
|
||||||
if (isNaN(length) || length === 0) {
|
prevEndPoint = prev
|
||||||
//마지막 추가 된 points 제거합니다.
|
return circle
|
||||||
|
})
|
||||||
|
|
||||||
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
historyPoints.current.push(circle)
|
||||||
|
points.current.push(circle)
|
||||||
|
canvas?.add(circle)
|
||||||
|
|
||||||
canvas?.remove(lastPoint)
|
if (points.current.length === 2) {
|
||||||
setEndPoint(prevEndPoint)
|
if (guideLineMode || guideDotMode) {
|
||||||
historyPoints.current.pop()
|
const vector = {
|
||||||
points.current.pop()
|
x: points.current[1].left - points.current[0].left,
|
||||||
return
|
y: points.current[1].top - points.current[0].top,
|
||||||
|
}
|
||||||
|
const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
||||||
|
|
||||||
|
let scaledVector
|
||||||
|
|
||||||
|
if (slope >= 1) {
|
||||||
|
// 기울기가 1 이상이면 x축 방향으로 그림
|
||||||
|
scaledVector = {
|
||||||
|
x: 0,
|
||||||
|
y: pointer.y - prevEndPoint?.top,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 기울기가 1 미만이면 y축 방향으로 그림
|
||||||
|
scaledVector = {
|
||||||
|
x: pointer.x - prevEndPoint?.left,
|
||||||
|
y: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const verticalLength = scaledVector.y
|
||||||
|
const horizontalLength = scaledVector.x
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
canvas?.renderAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const length = Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
|
// length 값이 숫자가 아닌 경우
|
||||||
|
if (isNaN(length) || length === 0) {
|
||||||
|
//마지막 추가 된 points 제거합니다.
|
||||||
|
|
||||||
|
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||||
|
|
||||||
|
canvas?.remove(lastPoint)
|
||||||
|
setEndPoint(prevEndPoint)
|
||||||
|
historyPoints.current.pop()
|
||||||
|
points.current.pop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length) {
|
||||||
|
const vector = {
|
||||||
|
x: points.current[1].left - points.current[0].left,
|
||||||
|
y: points.current[1].top - points.current[0].top,
|
||||||
|
}
|
||||||
|
const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
||||||
|
|
||||||
|
let scaledVector
|
||||||
|
if (slope >= 1) {
|
||||||
|
// 기울기가 1 이상이면 x축 방향으로 그림
|
||||||
|
scaledVector = {
|
||||||
|
x: 0,
|
||||||
|
y: vector.y >= 0 ? Number(length) : -Number(length),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 기울기가 1 미만이면 y축 방향으로 그림
|
||||||
|
scaledVector = {
|
||||||
|
x: vector.x >= 0 ? Number(length) : -Number(length),
|
||||||
|
y: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const verticalLength = scaledVector.y
|
||||||
|
const horizontalLength = scaledVector.x
|
||||||
|
|
||||||
|
drawCircleAndLine(verticalLength, horizontalLength)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length) {
|
canvas?.renderAll()
|
||||||
const vector = {
|
},
|
||||||
x: points.current[1].left - points.current[0].left,
|
[canvas],
|
||||||
y: points.current[1].top - points.current[0].top,
|
),
|
||||||
}
|
textboxMode: useCallback((options) => {
|
||||||
const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
|
||||||
|
|
||||||
let scaledVector
|
|
||||||
if (slope >= 1) {
|
|
||||||
// 기울기가 1 이상이면 x축 방향으로 그림
|
|
||||||
scaledVector = {
|
|
||||||
x: 0,
|
|
||||||
y: vector.y >= 0 ? Number(length) : -Number(length),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 기울기가 1 미만이면 y축 방향으로 그림
|
|
||||||
scaledVector = {
|
|
||||||
x: vector.x >= 0 ? Number(length) : -Number(length),
|
|
||||||
y: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const verticalLength = scaledVector.y
|
|
||||||
const horizontalLength = scaledVector.x
|
|
||||||
|
|
||||||
drawCircleAndLine(verticalLength, horizontalLength)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas?.renderAll()
|
|
||||||
},
|
|
||||||
textboxMode: (options) => {
|
|
||||||
if (canvas?.getActiveObject()?.type === 'textbox') return
|
if (canvas?.getActiveObject()?.type === 'textbox') return
|
||||||
const pointer = canvas?.getPointer(options.e)
|
const pointer = canvas?.getPointer(options.e)
|
||||||
|
|
||||||
@ -819,8 +861,8 @@ export function useMode() {
|
|||||||
textbox?.on('editing:exited', function () {
|
textbox?.on('editing:exited', function () {
|
||||||
changeMode(canvas, Mode.EDIT)
|
changeMode(canvas, Mode.EDIT)
|
||||||
})
|
})
|
||||||
},
|
}, []),
|
||||||
drawRectMode: (o) => {
|
drawRectMode: useCallback((o) => {
|
||||||
let rect, isDown, origX, origY
|
let rect, isDown, origX, origY
|
||||||
isDown = true
|
isDown = true
|
||||||
const pointer = canvas.getPointer(o.e)
|
const pointer = canvas.getPointer(o.e)
|
||||||
@ -860,36 +902,39 @@ export function useMode() {
|
|||||||
canvas.off('mouse:up')
|
canvas.off('mouse:up')
|
||||||
setMode(Mode.DEFAULT)
|
setMode(Mode.DEFAULT)
|
||||||
})
|
})
|
||||||
},
|
}, []),
|
||||||
// 흡착점 추가
|
// 흡착점 추가
|
||||||
adsorptionPoint(o) {
|
adsorptionPoint: useCallback(
|
||||||
const pointer = canvas.getPointer(o.e)
|
(o) => {
|
||||||
let newX = pointer.x
|
const pointer = canvas.getPointer(o.e)
|
||||||
let newY = pointer.y
|
let newX = pointer.x
|
||||||
|
let newY = pointer.y
|
||||||
|
|
||||||
if (getInterSectPointByMouseLine()) {
|
if (getInterSectPointByMouseLine()) {
|
||||||
const interSectPoint = getInterSectPointByMouseLine()
|
const interSectPoint = getInterSectPointByMouseLine()
|
||||||
newX = interSectPoint.x
|
newX = interSectPoint.x
|
||||||
newY = interSectPoint.y
|
newY = interSectPoint.y
|
||||||
}
|
}
|
||||||
|
|
||||||
const circle = new fabric.Circle({
|
const circle = new fabric.Circle({
|
||||||
radius: 5,
|
radius: 5,
|
||||||
fill: 'transparent', // 원 안을 비웁니다.
|
fill: 'transparent', // 원 안을 비웁니다.
|
||||||
stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
|
stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||||
left: newX,
|
left: newX,
|
||||||
top: newY,
|
top: newY,
|
||||||
originX: 'center',
|
originX: 'center',
|
||||||
originY: 'center',
|
originY: 'center',
|
||||||
x: newX - 5,
|
x: newX - 5,
|
||||||
y: newY - 5,
|
y: newY - 5,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
name: 'adsorptionPoint',
|
name: 'adsorptionPoint',
|
||||||
})
|
})
|
||||||
|
|
||||||
canvas.add(circle)
|
canvas.add(circle)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
},
|
},
|
||||||
|
[canvas],
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
const getInterSectPointByMouseLine = () => {
|
const getInterSectPointByMouseLine = () => {
|
||||||
@ -4484,7 +4529,6 @@ export function useMode() {
|
|||||||
|
|
||||||
canvas?.off('mouse:move')
|
canvas?.off('mouse:move')
|
||||||
canvas?.off('mouse:out')
|
canvas?.off('mouse:out')
|
||||||
document.removeEventListener('keydown', handleKeyDown)
|
|
||||||
const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof')
|
const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof')
|
||||||
roofs.forEach((roof, index) => {
|
roofs.forEach((roof, index) => {
|
||||||
const offsetPolygonPoint = offsetPolygon(roof.points, -20)
|
const offsetPolygonPoint = offsetPolygon(roof.points, -20)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user