Merge branch 'dev' into dev-yj
# Conflicts: # src/components/Roof2.jsx
This commit is contained in:
commit
f9b84f42d6
@ -1,6 +1,7 @@
|
|||||||
NEXT_PUBLIC_TEST="테스트변수입니다. development"
|
NEXT_PUBLIC_TEST="테스트변수입니다. development"
|
||||||
|
|
||||||
NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080"
|
NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080"
|
||||||
|
# NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
|
||||||
|
|
||||||
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
|
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
"react-responsive-modal": "^6.4.2",
|
"react-responsive-modal": "^6.4.2",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^10.0.5",
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@turf/turf": "^7.0.0",
|
"@turf/turf": "^7.0.0",
|
||||||
|
|||||||
@ -3,7 +3,13 @@ import RoofSelect from '@/app/[locale]/roof2/RoofSelect'
|
|||||||
import { initCheck } from '@/util/session-util'
|
import { initCheck } from '@/util/session-util'
|
||||||
|
|
||||||
export default async function Roof2Page() {
|
export default async function Roof2Page() {
|
||||||
await initCheck()
|
const session = await initCheck()
|
||||||
|
const roof2Props = {
|
||||||
|
name: session.name || '',
|
||||||
|
userId: session.userId || '',
|
||||||
|
email: session.email || '',
|
||||||
|
isLoggedIn: session.isLoggedIn,
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -13,7 +19,7 @@ export default async function Roof2Page() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center my-8 pt-20">
|
<div className="flex flex-col justify-center my-8 pt-20">
|
||||||
<Roof2 />
|
<Roof2 {...roof2Props} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export default function Headers() {
|
|||||||
<div className="space-x-4 text-xl">
|
<div className="space-x-4 text-xl">
|
||||||
<Link href="/intro">Intro</Link>
|
<Link href="/intro">Intro</Link>
|
||||||
<Link href="/playground">Playground</Link>
|
<Link href="/playground">Playground</Link>
|
||||||
|
<Link href="/settings">Canvas Settings</Link>
|
||||||
<Link href="/roof">Roof</Link>
|
<Link href="/roof">Roof</Link>
|
||||||
<Link href="/roof2">Roof2</Link>
|
<Link href="/roof2">Roof2</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
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 { useMode } from '@/hooks/useMode'
|
||||||
import { Mode } from '@/common/common'
|
import { Mode } from '@/common/common'
|
||||||
import { Button } from '@nextui-org/react'
|
import { Button } from '@nextui-org/react'
|
||||||
@ -26,7 +27,8 @@ import QContextMenu from './common/context-menu/QContextMenu'
|
|||||||
import { modalContent, modalState } from '@/store/modalAtom'
|
import { modalContent, modalState } from '@/store/modalAtom'
|
||||||
import SettingsModal from './SettingsModal'
|
import SettingsModal from './SettingsModal'
|
||||||
|
|
||||||
export default function Roof2() {
|
export default function Roof2(props) {
|
||||||
|
const { name, userId, email, isLoggedIn } = props
|
||||||
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
||||||
|
|
||||||
const canvasRef = useRef(null)
|
const canvasRef = useRef(null)
|
||||||
@ -65,6 +67,7 @@ export default function Roof2() {
|
|||||||
const [thumbnails, setThumbnails] = useState([])
|
const [thumbnails, setThumbnails] = useState([])
|
||||||
const thumbnailProps = {
|
const thumbnailProps = {
|
||||||
thumbnails,
|
thumbnails,
|
||||||
|
canvas,
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -90,6 +93,23 @@ export default function Roof2() {
|
|||||||
|
|
||||||
// const [canvasState, setCanvasState] = useRecoilState(canvasAtom)
|
// const [canvasState, setCanvasState] = useRecoilState(canvasAtom)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get({ url: `/api/canvas-management/canvas-statuses/by-object/test123240822001` }).then((res) => {
|
||||||
|
const arrangeData = res.map((item) => {
|
||||||
|
console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, ''))
|
||||||
|
const test = item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')
|
||||||
|
const test2 = test.substring(1, test.length - 1)
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
userId: item.userId,
|
||||||
|
imageName: `/canvasState/${item.imageName}.png`,
|
||||||
|
canvasStatus: JSON.stringify(test2),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setThumbnails(arrangeData)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
return
|
return
|
||||||
@ -531,6 +551,16 @@ export default function Roof2() {
|
|||||||
setCompass(degree)
|
setCompass(degree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const changeLength = (e) => {
|
||||||
|
setScale(e)
|
||||||
|
const polygon = canvas?.getActiveObject()
|
||||||
|
if (polygon.type !== 'QPolygon') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{canvas && (
|
{canvas && (
|
||||||
@ -636,7 +666,7 @@ export default function Roof2() {
|
|||||||
<Button
|
<Button
|
||||||
className="m-1 p-2"
|
className="m-1 p-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCanvasBackgroundWithDots(canvas, 20)
|
setCanvasBackgroundWithDots(canvas, 200)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
점선 추가
|
점선 추가
|
||||||
@ -646,7 +676,7 @@ export default function Roof2() {
|
|||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Button className="m-1 p-2" onClick={() => saveImage('title')}>
|
<Button className="m-1 p-2" onClick={() => saveImage(uuidv4(), userId, setThumbnails)}>
|
||||||
저장
|
저장
|
||||||
</Button>
|
</Button>
|
||||||
{/*<Button className="m-1 p-2" onClick={rotateShape}>
|
{/*<Button className="m-1 p-2" onClick={rotateShape}>
|
||||||
@ -714,6 +744,9 @@ export default function Roof2() {
|
|||||||
<div className="m-2 p-2 w-80">
|
<div className="m-2 p-2 w-80">
|
||||||
<RangeSlider title={`글자 크기${fontSize}`} initValue={fontSize} onchange={setFontSize} />
|
<RangeSlider title={`글자 크기${fontSize}`} initValue={fontSize} onchange={setFontSize} />
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,10 +1,18 @@
|
|||||||
import { Card, Image } from '@nextui-org/react'
|
'use client'
|
||||||
|
|
||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
|
import { Card, Image } from '@nextui-org/react'
|
||||||
|
|
||||||
function ThumbnailList(props) {
|
function ThumbnailList(props) {
|
||||||
const { thumbnails } = props
|
const { thumbnails, canvas } = props
|
||||||
|
|
||||||
console.log('ThumbnailList')
|
const handleSelectThumb = (canvasStatus) => {
|
||||||
|
console.log('canvasStatus', canvasStatus.length)
|
||||||
|
canvas?.clear() // 캔버스를 초기화합니다.
|
||||||
|
canvas?.loadFromJSON(JSON.parse(canvasStatus), function () {
|
||||||
|
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -12,7 +20,14 @@ function ThumbnailList(props) {
|
|||||||
{thumbnails.length > 0 &&
|
{thumbnails.length > 0 &&
|
||||||
thumbnails.map((thumbnail, index) => (
|
thumbnails.map((thumbnail, index) => (
|
||||||
<Card isFooterBlurred radius="lg" className="border-none m-2">
|
<Card isFooterBlurred radius="lg" className="border-none m-2">
|
||||||
<Image alt="Woman listing to music" className="object-cover" height={200} src="https://nextui.org/images/hero-card.jpeg" width={200} />
|
<Image
|
||||||
|
alt="Woman listing to music"
|
||||||
|
className="object-cover"
|
||||||
|
height={200}
|
||||||
|
src={thumbnail.imageName}
|
||||||
|
width={200}
|
||||||
|
onClick={() => handleSelectThumb(thumbnail.canvasStatus)}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
|
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
|
||||||
|
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
|
import { canvasSizeState, fontSizeState, guidePointModeState } from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { defineQLine } from '@/util/qline-utils'
|
import { defineQLine } from '@/util/qline-utils'
|
||||||
import { defineQPloygon } from '@/util/qpolygon-utils'
|
import { defineQPloygon } from '@/util/qpolygon-utils'
|
||||||
import { writeImage } from '@/lib/canvas'
|
import { writeImage } from '@/lib/canvas'
|
||||||
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
||||||
|
import { post } from '@/lib/Axios'
|
||||||
|
|
||||||
export function useCanvas(id) {
|
export function useCanvas(id) {
|
||||||
const [canvas, setCanvas] = useState()
|
const [canvas, setCanvas] = useState()
|
||||||
@ -19,6 +20,7 @@ export function useCanvas(id) {
|
|||||||
const [canvasSize] = useRecoilState(canvasSizeState)
|
const [canvasSize] = useRecoilState(canvasSizeState)
|
||||||
const [fontSize] = useRecoilState(fontSizeState)
|
const [fontSize] = useRecoilState(fontSizeState)
|
||||||
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
|
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
|
||||||
|
const setGuidePointMode = useSetRecoilState(guidePointModeState)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 처음 셋팅
|
* 처음 셋팅
|
||||||
@ -333,7 +335,7 @@ export function useCanvas(id) {
|
|||||||
* 이미지로 저장하는 함수
|
* 이미지로 저장하는 함수
|
||||||
* @param {string} title - 저장할 이미지 이름
|
* @param {string} title - 저장할 이미지 이름
|
||||||
*/
|
*/
|
||||||
const saveImage = async (title = 'canvas') => {
|
const saveImage = async (title = 'canvas', userId, setThumbnails) => {
|
||||||
removeMouseLines()
|
removeMouseLines()
|
||||||
await writeImage(title, canvas?.toDataURL('image/png').replace('data:image/png;base64,', ''))
|
await writeImage(title, canvas?.toDataURL('image/png').replace('data:image/png;base64,', ''))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -342,6 +344,19 @@ export function useCanvas(id) {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log('err', err)
|
console.log('err', err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const canvasStatus = addCanvas()
|
||||||
|
|
||||||
|
const patternData = {
|
||||||
|
userId: userId,
|
||||||
|
imageName: title,
|
||||||
|
objectNo: 'test123240822001',
|
||||||
|
canvasStatus: JSON.stringify(canvasStatus).replace(/"/g, '##'),
|
||||||
|
}
|
||||||
|
|
||||||
|
await post({ url: '/api/canvas-management/canvas-statuses', data: patternData })
|
||||||
|
|
||||||
|
setThumbnails((prev) => [...prev, { imageName: `/canvasState/${title}.png`, userId, canvasStatus: JSON.stringify(canvasStatus) }])
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFlip = () => {
|
const handleFlip = () => {
|
||||||
@ -386,6 +401,7 @@ export function useCanvas(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const setCanvasBackgroundWithDots = (canvas, gap) => {
|
const setCanvasBackgroundWithDots = (canvas, gap) => {
|
||||||
|
setGuidePointMode(true)
|
||||||
// Create a new canvas and fill it with dots
|
// Create a new canvas and fill it with dots
|
||||||
const tempCanvas = new fabric.StaticCanvas()
|
const tempCanvas = new fabric.StaticCanvas()
|
||||||
tempCanvas.setDimensions({
|
tempCanvas.setDimensions({
|
||||||
@ -435,15 +451,16 @@ export function useCanvas(id) {
|
|||||||
const str = JSON.stringify(objs)
|
const str = JSON.stringify(objs)
|
||||||
|
|
||||||
canvas?.clear()
|
canvas?.clear()
|
||||||
|
return str
|
||||||
|
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
// // 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
||||||
canvas?.loadFromJSON(JSON.parse(str), function () {
|
// canvas?.loadFromJSON(JSON.parse(str), function () {
|
||||||
// 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
// // 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
||||||
console.log(canvas?.getObjects().filter((obj) => obj.name === 'roof'))
|
// console.log(canvas?.getObjects().filter((obj) => obj.name === 'roof'))
|
||||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
// canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
})
|
// })
|
||||||
}, 1000)
|
// }, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -18,9 +18,6 @@ export function useCanvasEvent() {
|
|||||||
canvas?.on('object:added', () => {
|
canvas?.on('object:added', () => {
|
||||||
document.addEventListener('keydown', handleKeyDown)
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
})
|
})
|
||||||
|
|
||||||
canvas?.on('mouse:move', drawMouseLines)
|
|
||||||
canvas?.on('mouse:out', removeMouseLines)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
|
|||||||
@ -7,23 +7,22 @@ import {
|
|||||||
getDirection,
|
getDirection,
|
||||||
getStartIndex,
|
getStartIndex,
|
||||||
rearrangeArray,
|
rearrangeArray,
|
||||||
getRoofHeight,
|
|
||||||
getDegreeByChon,
|
|
||||||
} from '@/util/canvas-util'
|
} from '@/util/canvas-util'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
canvasSizeState,
|
canvasSizeState,
|
||||||
|
compassState,
|
||||||
drewRoofCellsState,
|
drewRoofCellsState,
|
||||||
fontSizeState,
|
fontSizeState,
|
||||||
|
guidePointModeState,
|
||||||
|
modeState,
|
||||||
roofPolygonArrayState,
|
roofPolygonArrayState,
|
||||||
roofPolygonPatternArrayState,
|
roofPolygonPatternArrayState,
|
||||||
roofState,
|
roofState,
|
||||||
sortedPolygonArray,
|
sortedPolygonArray,
|
||||||
templateTypeState,
|
templateTypeState,
|
||||||
wallState,
|
wallState,
|
||||||
compassState,
|
|
||||||
modeState,
|
|
||||||
} from '@/store/canvasAtom'
|
} from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
@ -46,6 +45,7 @@ export function useMode() {
|
|||||||
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
|
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
|
||||||
const [roof, setRoof] = useRecoilState(roofState)
|
const [roof, setRoof] = useRecoilState(roofState)
|
||||||
const [wall, setWall] = useRecoilState(wallState)
|
const [wall, setWall] = useRecoilState(wallState)
|
||||||
|
const isGuidePointMode = useRecoilValue(guidePointModeState)
|
||||||
|
|
||||||
const [endPoint, setEndPoint] = useState(null)
|
const [endPoint, setEndPoint] = useState(null)
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ export function useMode() {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
document.addEventListener('keydown', handleKeyDown)
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
|
canvas?.on('mouse:move', drawMouseLines)
|
||||||
// 컴포넌트가 언마운트될 때 이벤트 리스너 제거
|
// 컴포넌트가 언마운트될 때 이벤트 리스너 제거
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', handleKeyDown)
|
document.removeEventListener('keydown', handleKeyDown)
|
||||||
@ -94,6 +94,15 @@ export function useMode() {
|
|||||||
canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
|
canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
|
||||||
}, [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 drawMouseLines = (e) => {
|
||||||
// 현재 마우스 포인터의 위치를 가져옵니다.
|
// 현재 마우스 포인터의 위치를 가져옵니다.
|
||||||
const pointer = canvas?.getPointer(e.e)
|
const pointer = canvas?.getPointer(e.e)
|
||||||
@ -104,9 +113,17 @@ export function useMode() {
|
|||||||
if (canvas?.getActiveObject()) {
|
if (canvas?.getActiveObject()) {
|
||||||
return
|
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',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
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',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@ -206,8 +223,17 @@ export function useMode() {
|
|||||||
|
|
||||||
const pointer = canvas?.getPointer(e.e)
|
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 생성
|
// 마우스 포인터 위치랑 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',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@ -529,13 +555,18 @@ export function useMode() {
|
|||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
},
|
},
|
||||||
editMode: (options) => {
|
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({
|
const circle = new fabric.Circle({
|
||||||
radius: 5,
|
radius: 5,
|
||||||
fill: 'transparent', // 원 안을 비웁니다.
|
fill: 'transparent', // 원 안을 비웁니다.
|
||||||
stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
|
stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
|
||||||
left: pointer.x - 5,
|
left: pointer.x,
|
||||||
top: pointer.y - 5,
|
top: pointer.y,
|
||||||
originX: 'center',
|
originX: 'center',
|
||||||
originY: 'center',
|
originY: 'center',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@ -544,14 +575,48 @@ export function useMode() {
|
|||||||
startPoint.current = circle
|
startPoint.current = circle
|
||||||
pointCount.current = pointCount.current + 1
|
pointCount.current = pointCount.current + 1
|
||||||
}
|
}
|
||||||
|
let prevEndPoint
|
||||||
|
|
||||||
setEndPoint(circle)
|
setEndPoint((prev) => {
|
||||||
|
prevEndPoint = prev
|
||||||
|
return circle
|
||||||
|
})
|
||||||
|
|
||||||
historyPoints.current.push(circle)
|
historyPoints.current.push(circle)
|
||||||
points.current.push(circle)
|
points.current.push(circle)
|
||||||
canvas?.add(circle)
|
canvas?.add(circle)
|
||||||
|
|
||||||
if (points.current.length === 2) {
|
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('길이를 입력하세요:'))
|
const length = Number(prompt('길이를 입력하세요:'))
|
||||||
|
|
||||||
// length 값이 숫자가 아닌 경우
|
// length 값이 숫자가 아닌 경우
|
||||||
@ -561,7 +626,7 @@ export function useMode() {
|
|||||||
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||||
|
|
||||||
canvas?.remove(lastPoint)
|
canvas?.remove(lastPoint)
|
||||||
|
setEndPoint(prevEndPoint)
|
||||||
historyPoints.current.pop()
|
historyPoints.current.pop()
|
||||||
points.current.pop()
|
points.current.pop()
|
||||||
return
|
return
|
||||||
|
|||||||
@ -24,32 +24,32 @@ axiosInstance.interceptors.request.use(undefined, (error) => {
|
|||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
export const get = (url) =>
|
export const get = ({ url }) =>
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(url)
|
.get(url)
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
export const post = (url, data) =>
|
export const post = ({ url, data }) =>
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(url, data)
|
.post(url, data)
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
export const put = (url, data) =>
|
export const put = ({ url, data }) =>
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.put(url, data)
|
.put(url, data)
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
export const patch = (url, data) =>
|
export const patch = ({ url, data }) =>
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.patch(url, data)
|
.patch(url, data)
|
||||||
|
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
export const del = (url) =>
|
export const del = ({ url }) =>
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.delete(url)
|
.delete(url)
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
|
|||||||
@ -48,8 +48,9 @@ export async function login(formData) {
|
|||||||
throw Error('Wrong Credentials!')
|
throw Error('Wrong Credentials!')
|
||||||
}
|
}
|
||||||
|
|
||||||
session.name = loginUser.USER_ID
|
session.name = loginUser.name
|
||||||
session.email = loginUser.SALE_STORE_ID
|
session.userId = loginUser.userId
|
||||||
|
session.email = loginUser.email
|
||||||
session.isLoggedIn = true
|
session.isLoggedIn = true
|
||||||
console.log('session:', session)
|
console.log('session:', session)
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,16 @@ export const modeState = atom({
|
|||||||
default: 'default',
|
default: 'default',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const guidePointModeState = atom({
|
||||||
|
key: 'guidePointModeState',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const guideModeLineState = atom({
|
||||||
|
key: 'guideLineModeState',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
export const fontSizeState = atom({
|
export const fontSizeState = atom({
|
||||||
key: 'fontSizeState',
|
key: 'fontSizeState',
|
||||||
default: 16,
|
default: 16,
|
||||||
|
|||||||
@ -7,4 +7,6 @@ export const initCheck = async () => {
|
|||||||
if (!session.isLoggedIn) {
|
if (!session.isLoggedIn) {
|
||||||
redirect('/login')
|
redirect('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return session
|
||||||
}
|
}
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@ -6108,16 +6108,16 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
|||||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||||
|
|
||||||
|
uuid@^10.0.0:
|
||||||
|
version "10.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
|
||||||
|
integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
|
||||||
|
|
||||||
uuid@^8.3.0:
|
uuid@^8.3.0:
|
||||||
version "8.3.2"
|
version "8.3.2"
|
||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
|
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
uuid@^9.0.1:
|
|
||||||
version "9.0.1"
|
|
||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz"
|
|
||||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
|
||||||
|
|
||||||
w3c-hr-time@^1.0.2:
|
w3c-hr-time@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user