This commit is contained in:
hyojun.choi 2024-09-09 11:03:41 +09:00
commit dee5f23f1c
10 changed files with 134 additions and 15 deletions

View File

@ -25,6 +25,7 @@
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-datepicker": "^7.3.0", "react-datepicker": "^7.3.0",
"react-dom": "^18", "react-dom": "^18",
"react-icons": "^5.3.0",
"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",

View File

@ -0,0 +1,5 @@
import FloorPlan from '@/components/floor-plan/FloorPlan'
export default function floorPlanPage() {
return <FloorPlan />
}

View File

@ -0,0 +1,29 @@
'use server'
import fs from 'fs/promises'
import { NextResponse } from 'next/server'
export async function GET(req) {
const path = 'public/mapImages'
const q = req.nextUrl.searchParams.get('q')
const fileNm = req.nextUrl.searchParams.get('fileNm')
const zoom = req.nextUrl.searchParams.get('zoom')
const targetUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${q}&zoom=${zoom}&maptype=satellite&size=640x640&scale=1&key=AIzaSyDO7nVR1N_D2tKy60hgGFavpLaXkHpiHpc`
const decodeUrl = decodeURIComponent(targetUrl)
const response = await fetch(decodeUrl)
const data = await response.arrayBuffer()
const buffer = Buffer.from(data)
try {
await fs.readdir(path)
} catch {
await fs.mkdir(path)
} finally {
await fs.writeFile(`${path}/${fileNm}.png`, buffer)
}
return NextResponse.json({ fileNm: `${fileNm}.png` })
}

View File

@ -1,25 +1,32 @@
'use client' 'use client'
import { useRef, useState } from 'react' import { useRef, useState } from 'react'
import { Button } from '@nextui-org/react' import { useRecoilState } from 'recoil'
import ColorPicker from './common/color-picker/ColorPicker' import { v4 as uuidv4 } from 'uuid'
import { FaAnglesUp } from 'react-icons/fa6'
import { FaAnglesDown } from 'react-icons/fa6'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { convertDwgToPng } from '@/lib/cadAction' import { convertDwgToPng } from '@/lib/cadAction'
// import { get } from '@/lib/Axios' import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom'
import QSelect from '@/components/ui/QSelect' import QSelect from '@/components/ui/QSelect'
import { Button } from '@nextui-org/react'
import ColorPicker from './common/color-picker/ColorPicker'
import { toastUp } from '@/hooks/useToast'
import styles from './playground.module.css' import styles from './playground.module.css'
import { useRecoilState } from 'recoil' import Image from 'next/image'
import { cadFileNameState, useCadFileState } from '@/store/canvasAtom'
import { toastUp } from '@/hooks/useToast'
export default function Playground() { export default function Playground() {
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState)
const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState)
const fileRef = useRef(null) const fileRef = useRef(null)
const queryRef = useRef(null)
const [zoom, setZoom] = useState(20)
const { get, promisePost } = useAxios() const { get, promisePost } = useAxios()
const testVar = process.env.NEXT_PUBLIC_TEST const testVar = process.env.NEXT_PUBLIC_TEST
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
@ -56,6 +63,26 @@ export default function Playground() {
}) })
} }
const handleDownImage = async (fileName = '') => {
const fileNm = fileName === '' ? uuidv4() : fileName
const queryString = queryRef.current.value === '' ? '서울시 서대문구 연세로5다길 22-3 발리빌라 3층' : queryRef.current.value
const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryString}&fileNm=${fileNm}&zoom=${zoom}` })
console.log('res', res)
setGoogleMapFileName(res.fileNm)
toastUp({ message: '이미지 저장 완료', type: 'success' })
setUseGoogleMapFile(true)
}
const handleZoom = async (type) => {
if (type === 'up') {
setZoom((prevState) => prevState + 1)
} else {
setZoom((prevState) => prevState - 1)
}
await handleDownImage()
}
const data = [ const data = [
{ {
id: 1, id: 1,
@ -99,11 +126,31 @@ export default function Playground() {
<div className="p-4">{color}</div> <div className="p-4">{color}</div>
</div> </div>
<div> <div>
<h1 className="text-2xl">캐드 파일 이미지 사용</h1>
<input type="file" name="file" ref={fileRef} /> <input type="file" name="file" ref={fileRef} />
<div> <div>
<Button onClick={handleConvert}>Convert</Button> <Button onClick={handleConvert}>Convert</Button>
</div> </div>
</div> </div>
<div>
<h1 className="text-2xl">구글 이미지 사용</h1>
<input type="text" ref={queryRef} className="w-80 border-medium my-2" />
<div>
<Button onClick={handleDownImage}>Google map Download to Image</Button>
</div>
{useGoogleMapFile && (
<>
<div className="my-2">
<p className="text-lg">Zoom Controller : {zoom}</p>
<Button startContent={<FaAnglesUp />} className="mx-2" onClick={() => handleZoom('up')}></Button>
<Button startContent={<FaAnglesDown />} className="mx-2" onClick={() => handleZoom('down')}></Button>
</div>
<div className="my-2">
<Image src={`/mapImages/${googleMapFileName}`} width={640} height={640} />
</div>
</>
)}
</div>
</div> </div>
</> </>
) )

View File

@ -16,11 +16,13 @@ import {
currentObjectState, currentObjectState,
fontSizeState, fontSizeState,
globalCompassState, globalCompassState,
googleMapFileNameState,
roofMaterialState, roofMaterialState,
roofState, roofState,
sortedPolygonArray, sortedPolygonArray,
templateTypeState, templateTypeState,
useCadFileState, useCadFileState,
useGoogleMapFileState,
wallState, wallState,
} from '@/store/canvasAtom' } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
@ -50,7 +52,7 @@ export default function Roof2(props) {
setCanvasBackgroundWithDots, setCanvasBackgroundWithDots,
saveImage, saveImage,
addCanvas, addCanvas,
handleCadImageLoad, handleBackImageLoadToCanvas,
handleCadImageInit, handleCadImageInit,
backImg, backImg,
setBackImg, setBackImg,
@ -100,13 +102,18 @@ export default function Roof2(props) {
canvas, canvas,
} }
let imgPath
// cad // cad
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState) const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState)
let imgPath
useCadFile && (imgPath = `/cadImages/${cadFileName}`) useCadFile && (imgPath = `/cadImages/${cadFileName}`)
//
const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState)
const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState)
useGoogleMapFile && (imgPath = `/mapImages/${googleMapFileName}`)
const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState) const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState)
const { const {
@ -158,7 +165,11 @@ export default function Roof2(props) {
if (!cadFileComplete && useCadFile) { if (!cadFileComplete && useCadFile) {
// cad // cad
useCadFile && handleCadImageLoad(imgPath, canvas) useCadFile && handleBackImageLoadToCanvas(imgPath, canvas)
}
if (useGoogleMapFile) {
handleBackImageLoadToCanvas(imgPath, canvas)
} }
}, [canvas, mode]) }, [canvas, mode])
@ -822,6 +833,7 @@ export default function Roof2(props) {
backImg backImg
.set({ .set({
selectable: false, selectable: false,
opacity: 0.7,
}) })
.sendToBack() .sendToBack()
canvas.clear() canvas.clear()
@ -831,7 +843,7 @@ export default function Roof2(props) {
} }
}} }}
> >
cad 파일 조정 완료 배경 이미지 조정 완료
</Button> </Button>
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}> <Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`} canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}

View File

@ -12,9 +12,11 @@ export default function QContextMenu(props) {
let contextType = '' let contextType = ''
if (activeObject) { if (activeObject) {
// if (activeObject.initOptions) {
if (activeObject.initOptions.name.indexOf('guide') > -1) { //
contextType = 'surface' // if (activeObject.initOptions.name.indexOf('guide') > -1) {
contextType = 'surface' //
}
} }
} }

View File

@ -0,0 +1,7 @@
export default function FloorPlan() {
return (
<>
<h1>도면 작성 페이지</h1>
</>
)
}

View File

@ -449,7 +449,7 @@ export function useCanvas(id) {
/** /**
* cad 파일 사용시 이미지 로딩 함수 * cad 파일 사용시 이미지 로딩 함수
*/ */
const handleCadImageLoad = (url) => { const handleBackImageLoadToCanvas = (url) => {
console.log('image load url: ', url) console.log('image load url: ', url)
fabric.Image.fromURL(url, function (img) { fabric.Image.fromURL(url, function (img) {
@ -485,7 +485,7 @@ export function useCanvas(id) {
setCanvasBackgroundWithDots, setCanvasBackgroundWithDots,
addCanvas, addCanvas,
removeMouseLines, removeMouseLines,
handleCadImageLoad, handleBackImageLoadToCanvas,
handleCadImageInit, handleCadImageInit,
backImg, backImg,
setBackImg, setBackImg,

View File

@ -145,6 +145,17 @@ export const cadFileCompleteState = atom({
default: false, default: false,
}) })
export const useGoogleMapFileState = atom({
key: 'useGoogleMapFile',
default: false,
})
// 구글맵 저장 이미지 파일 이름
export const googleMapFileNameState = atom({
key: 'googleMapFileName',
default: '',
})
export const globalCompassState = atom({ export const globalCompassState = atom({
key: 'globalCompass', key: 'globalCompass',
default: 0, default: 0,

View File

@ -5515,6 +5515,11 @@ react-dom@^18:
loose-envify "^1.1.0" loose-envify "^1.1.0"
scheduler "^0.23.2" scheduler "^0.23.2"
react-icons@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.3.0.tgz#ccad07a30aebd40a89f8cfa7d82e466019203f1c"
integrity sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==
react-is@^16.13.1: react-is@^16.13.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"