Merge branch 'dev' into dev-test2
This commit is contained in:
commit
693a80a061
@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useCanvas } from '@/hooks/useCanvas'
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useMode } from '@/hooks/useMode'
|
||||
import { Button } from '@nextui-org/react'
|
||||
@ -59,6 +59,8 @@ export default function Roof2(props) {
|
||||
|
||||
const wall = useRecoilValue(wallState)
|
||||
|
||||
const [scale, setScale] = useState(1)
|
||||
|
||||
//canvas 썸네일
|
||||
const [thumbnails, setThumbnails] = useState([])
|
||||
const thumbnailProps = {
|
||||
@ -547,6 +549,16 @@ export default function Roof2(props) {
|
||||
setCompass(degree)
|
||||
}
|
||||
|
||||
const changeLength = (e) => {
|
||||
setScale(e)
|
||||
const polygon = canvas?.getActiveObject()
|
||||
if (polygon.type !== 'QPolygon') {
|
||||
return
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{canvas && (
|
||||
@ -643,7 +655,7 @@ export default function Roof2(props) {
|
||||
<Button
|
||||
className="m-1 p-2"
|
||||
onClick={() => {
|
||||
setCanvasBackgroundWithDots(canvas, 20)
|
||||
setCanvasBackgroundWithDots(canvas, 200)
|
||||
}}
|
||||
>
|
||||
점선 추가
|
||||
@ -721,6 +733,9 @@ export default function Roof2(props) {
|
||||
<div className="m-2 p-2 w-80">
|
||||
<RangeSlider title={`글자 크기${fontSize}`} initValue={fontSize} onchange={setFontSize} />
|
||||
</div>
|
||||
<div className="m-2 p-2 w-80">
|
||||
<RangeSlider title={`선택한 obj 가로 늘리기${scale}`} initValue={scale} min={0.01} max={2.0} step={0.01} onchange={changeLength} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { fabric } from 'fabric'
|
||||
|
||||
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
|
||||
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil'
|
||||
import { canvasSizeState, fontSizeState, guidePointModeState } from '@/store/canvasAtom'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
import { defineQLine } from '@/util/qline-utils'
|
||||
@ -20,6 +20,7 @@ export function useCanvas(id) {
|
||||
const [canvasSize] = useRecoilState(canvasSizeState)
|
||||
const [fontSize] = useRecoilState(fontSizeState)
|
||||
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
|
||||
const setGuidePointMode = useSetRecoilState(guidePointModeState)
|
||||
|
||||
/**
|
||||
* 처음 셋팅
|
||||
@ -400,6 +401,7 @@ export function useCanvas(id) {
|
||||
}
|
||||
|
||||
const setCanvasBackgroundWithDots = (canvas, gap) => {
|
||||
setGuidePointMode(true)
|
||||
// Create a new canvas and fill it with dots
|
||||
const tempCanvas = new fabric.StaticCanvas()
|
||||
tempCanvas.setDimensions({
|
||||
|
||||
@ -18,9 +18,6 @@ export function useCanvasEvent() {
|
||||
canvas?.on('object:added', () => {
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
})
|
||||
|
||||
canvas?.on('mouse:move', drawMouseLines)
|
||||
canvas?.on('mouse:out', removeMouseLines)
|
||||
}
|
||||
|
||||
const onChange = (e) => {
|
||||
|
||||
@ -7,23 +7,22 @@ import {
|
||||
getDirection,
|
||||
getStartIndex,
|
||||
rearrangeArray,
|
||||
getRoofHeight,
|
||||
getDegreeByChon,
|
||||
} from '@/util/canvas-util'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
|
||||
import {
|
||||
canvasSizeState,
|
||||
compassState,
|
||||
drewRoofCellsState,
|
||||
fontSizeState,
|
||||
guidePointModeState,
|
||||
modeState,
|
||||
roofPolygonArrayState,
|
||||
roofPolygonPatternArrayState,
|
||||
roofState,
|
||||
sortedPolygonArray,
|
||||
templateTypeState,
|
||||
wallState,
|
||||
compassState,
|
||||
modeState,
|
||||
} from '@/store/canvasAtom'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { fabric } from 'fabric'
|
||||
@ -46,6 +45,7 @@ export function useMode() {
|
||||
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
|
||||
const [roof, setRoof] = useRecoilState(roofState)
|
||||
const [wall, setWall] = useRecoilState(wallState)
|
||||
const isGuidePointMode = useRecoilValue(guidePointModeState)
|
||||
|
||||
const [endPoint, setEndPoint] = useState(null)
|
||||
|
||||
@ -67,11 +67,11 @@ export function useMode() {
|
||||
useEffect(() => {
|
||||
// 이벤트 리스너 추가
|
||||
// if (!canvas) {
|
||||
canvas?.setZoom(0.8)
|
||||
// canvas?.setZoom(0.8)
|
||||
// return
|
||||
// }
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
|
||||
canvas?.on('mouse:move', drawMouseLines)
|
||||
// 컴포넌트가 언마운트될 때 이벤트 리스너 제거
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
@ -94,6 +94,15 @@ export function useMode() {
|
||||
canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
|
||||
}, [endPoint])
|
||||
|
||||
useEffect(() => {
|
||||
canvas?.off('mouse:move')
|
||||
canvas?.on('mouse:move', drawMouseLines)
|
||||
if (mode === Mode.EDIT) {
|
||||
canvas?.off('mouse:down')
|
||||
canvas?.on('mouse:down', mouseEvent.editMode)
|
||||
}
|
||||
}, [mode, isGuidePointMode])
|
||||
|
||||
const drawMouseLines = (e) => {
|
||||
// 현재 마우스 포인터의 위치를 가져옵니다.
|
||||
const pointer = canvas?.getPointer(e.e)
|
||||
@ -104,9 +113,17 @@ export function useMode() {
|
||||
if (canvas?.getActiveObject()) {
|
||||
return
|
||||
}
|
||||
let newX, newY
|
||||
if (isGuidePointMode && mode === Mode.EDIT) {
|
||||
newX = Math.round(pointer.x / 200) * 200
|
||||
newY = Math.round(pointer.y / 200) * 200
|
||||
} else {
|
||||
newX = pointer.x
|
||||
newY = pointer.y
|
||||
}
|
||||
|
||||
// 가로선을 그립니다.
|
||||
const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], {
|
||||
const horizontalLine = new fabric.Line([0, newY, canvasSize.horizontal, newY], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
@ -114,7 +131,7 @@ export function useMode() {
|
||||
})
|
||||
|
||||
// 세로선을 그립니다.
|
||||
const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], {
|
||||
const verticalLine = new fabric.Line([newX, 0, newX, canvasSize.vertical], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
@ -206,8 +223,17 @@ export function useMode() {
|
||||
|
||||
const pointer = canvas?.getPointer(e.e)
|
||||
|
||||
let newX, newY
|
||||
if (isGuidePointMode && mode === Mode.EDIT) {
|
||||
newX = Math.round(pointer.x / 200) * 200
|
||||
newY = Math.round(pointer.y / 200) * 200
|
||||
} else {
|
||||
newX = pointer.x
|
||||
newY = pointer.y
|
||||
}
|
||||
|
||||
// 마우스 포인터 위치랑 endPoint를 연결하는 line 생성
|
||||
const line = new fabric.Line([endPoint.left, endPoint.top, pointer.x, pointer.y], {
|
||||
const line = new fabric.Line([endPoint.left, endPoint.top, newX, newY], {
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
selectable: false,
|
||||
@ -529,13 +555,18 @@ export function useMode() {
|
||||
canvas?.renderAll()
|
||||
},
|
||||
editMode: (options) => {
|
||||
const pointer = canvas?.getPointer(options.e)
|
||||
// const pointer = canvas?.getPointer(options.e)
|
||||
|
||||
const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
|
||||
|
||||
const pointer = calculateIntersection(mouseLines[0], mouseLines[1])
|
||||
|
||||
const circle = new fabric.Circle({
|
||||
radius: 5,
|
||||
fill: 'transparent', // 원 안을 비웁니다.
|
||||
stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||
left: pointer.x - 5,
|
||||
top: pointer.y - 5,
|
||||
left: pointer.x,
|
||||
top: pointer.y,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
selectable: false,
|
||||
@ -544,14 +575,48 @@ export function useMode() {
|
||||
startPoint.current = circle
|
||||
pointCount.current = pointCount.current + 1
|
||||
}
|
||||
let prevEndPoint
|
||||
|
||||
setEndPoint(circle)
|
||||
setEndPoint((prev) => {
|
||||
prevEndPoint = prev
|
||||
return circle
|
||||
})
|
||||
|
||||
historyPoints.current.push(circle)
|
||||
points.current.push(circle)
|
||||
canvas?.add(circle)
|
||||
|
||||
if (points.current.length === 2) {
|
||||
if (isGuidePointMode) {
|
||||
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('길이를 입력하세요:'))
|
||||
|
||||
// length 값이 숫자가 아닌 경우
|
||||
@ -561,7 +626,7 @@ export function useMode() {
|
||||
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||
|
||||
canvas?.remove(lastPoint)
|
||||
|
||||
setEndPoint(prevEndPoint)
|
||||
historyPoints.current.pop()
|
||||
points.current.pop()
|
||||
return
|
||||
|
||||
@ -10,6 +10,16 @@ export const modeState = atom({
|
||||
default: 'default',
|
||||
})
|
||||
|
||||
export const guidePointModeState = atom({
|
||||
key: 'guidePointModeState',
|
||||
default: false,
|
||||
})
|
||||
|
||||
export const guideModeLineState = atom({
|
||||
key: 'guideLineModeState',
|
||||
default: false,
|
||||
})
|
||||
|
||||
export const fontSizeState = atom({
|
||||
key: 'fontSizeState',
|
||||
default: 16,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user