diff --git a/package.json b/package.json index a91884a8..9f060d6d 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react-colorful": "^5.6.1", "react-datepicker": "^7.3.0", "react-dom": "^18", + "react-icons": "^5.3.0", "react-responsive-modal": "^6.4.2", "react-toastify": "^10.0.5", "recoil": "^0.7.7", diff --git a/src/app/[locale]/floor-plan/page.jsx b/src/app/[locale]/floor-plan/page.jsx new file mode 100644 index 00000000..7ca0fc3e --- /dev/null +++ b/src/app/[locale]/floor-plan/page.jsx @@ -0,0 +1,5 @@ +import FloorPlan from '@/components/floor-plan/FloorPlan' + +export default function floorPlanPage() { + return +} diff --git a/src/app/api/html2canvas/route.js b/src/app/api/html2canvas/route.js new file mode 100644 index 00000000..54af611d --- /dev/null +++ b/src/app/api/html2canvas/route.js @@ -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` }) +} diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 624113de..da470ab3 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -1,25 +1,32 @@ 'use client' import { useRef, useState } from 'react' -import { Button } from '@nextui-org/react' -import ColorPicker from './common/color-picker/ColorPicker' +import { useRecoilState } from 'recoil' +import { v4 as uuidv4 } from 'uuid' +import { FaAnglesUp } from 'react-icons/fa6' +import { FaAnglesDown } from 'react-icons/fa6' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' 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 { Button } from '@nextui-org/react' +import ColorPicker from './common/color-picker/ColorPicker' +import { toastUp } from '@/hooks/useToast' import styles from './playground.module.css' -import { useRecoilState } from 'recoil' -import { cadFileNameState, useCadFileState } from '@/store/canvasAtom' -import { toastUp } from '@/hooks/useToast' +import Image from 'next/image' export default function Playground() { const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) + const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) + const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) const fileRef = useRef(null) + const queryRef = useRef(null) + const [zoom, setZoom] = useState(20) const { get, promisePost } = useAxios() const testVar = process.env.NEXT_PUBLIC_TEST 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 = [ { id: 1, @@ -99,11 +126,31 @@ export default function Playground() {
{color}
+

캐드 파일 이미지 사용

+
+

구글 맵 이미지 사용

+ +
+ +
+ {useGoogleMapFile && ( + <> +
+

Zoom Controller : {zoom}

+ + +
+
+ +
+ + )} +
) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index d4ae8c1e..c8a48868 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -16,11 +16,13 @@ import { currentObjectState, fontSizeState, globalCompassState, + googleMapFileNameState, roofMaterialState, roofState, sortedPolygonArray, templateTypeState, useCadFileState, + useGoogleMapFileState, wallState, } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' @@ -50,7 +52,7 @@ export default function Roof2(props) { setCanvasBackgroundWithDots, saveImage, addCanvas, - handleCadImageLoad, + handleBackImageLoadToCanvas, handleCadImageInit, backImg, setBackImg, @@ -100,13 +102,18 @@ export default function Roof2(props) { canvas, } + let imgPath // cad 파일 업로드 const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState) - let imgPath useCadFile && (imgPath = `/cadImages/${cadFileName}`) + // 구글맵 이미지 업로드 + const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) + const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) + useGoogleMapFile && (imgPath = `/mapImages/${googleMapFileName}`) + const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState) const { @@ -158,7 +165,11 @@ export default function Roof2(props) { if (!cadFileComplete && useCadFile) { // cad 파일 로드 - useCadFile && handleCadImageLoad(imgPath, canvas) + useCadFile && handleBackImageLoadToCanvas(imgPath, canvas) + } + + if (useGoogleMapFile) { + handleBackImageLoadToCanvas(imgPath, canvas) } }, [canvas, mode]) @@ -822,6 +833,7 @@ export default function Roof2(props) { backImg .set({ selectable: false, + opacity: 0.7, }) .sendToBack() canvas.clear() @@ -831,7 +843,7 @@ export default function Roof2(props) { } }} > - cad 파일 조정 완료 + 배경 이미지 조정 완료