import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { useCanvas } from '../useCanvas' import { useAxios } from '../useAxios' import { usePlan } from '../usePlan' import { POLYGON_TYPE } from '@/common/common' import { QcastContext } from '@/app/QcastProvider' import { useContext } from 'react' /** * 이미지 로더 hook * @returns {function} handleCanvasToPng */ export function useImgLoader() { const canvas = useRecoilValue(canvasState) const { currentCanvasPlan } = usePlan() const { post } = useAxios() const { setIsGlobalLoading } = useContext(QcastContext) /** * 이미지 저장 시 왼쪽 위, 오른쪽 아래 좌표 * return [start, end] */ const getImageCoordinates = () => { const margin = 20 const objects = canvas.getObjects().filter((obj) => [POLYGON_TYPE.ROOF, 'lengthText', 'arrow'].includes(obj.name)) const minX = objects.reduce((acc, cur) => (cur.left < acc ? cur.left : acc), objects[0].left) const minY = objects.reduce((acc, cur) => (cur.top < acc ? cur.top : acc), objects[0].top) const maxX = objects.reduce((acc, cur) => (cur.left + cur.width > acc ? cur.left + cur.width : acc), 0) const maxY = objects.reduce((acc, cur) => (cur.top + cur.height > acc ? cur.top + cur.height : acc), 0) return [ { x: minX - margin, y: minY - margin }, { x: maxX + margin, y: maxY + margin }, ] } /** * 캔버스를 이미지로 저장 * @param {integer} type 1: 모듈만 있는 상태, 2: 가대까지 올린 상태 */ const handleCanvasToPng = async (type) => { try { removeMouseLines() canvas.getObjects('image').forEach((obj) => { if (obj.getSrc) { const img = new Image() img.crossOrigin = 'anonymous' img.src = obj.getSrc() obj.setElement(img) } }) canvas.renderAll() const formData = new FormData() const dataUrl = canvas.toDataURL('image/png') const blobBin = atob(dataUrl.split(',')[1]) const array = [] for (let i = 0; i < blobBin.length; i++) { array.push(blobBin.charCodeAt(i)) } const file = new Blob([new Uint8Array(array)], { type: 'image/png' }) formData.append('file', file, 'canvas.png') formData.append('objectNo', currentCanvasPlan.objectNo) formData.append('planNo', currentCanvasPlan.planNo) formData.append('type', type) // formData.append('coordinates', getImageCoordinates()) const positionObj = getImageCoordinates() console.log('🚀 ~ handleCanvasToPng ~ positionObj:', positionObj) formData.append('width', Math.round(positionObj[1].x - positionObj[0].x - 350)) formData.append('height', Math.round(positionObj[1].y - positionObj[0].y - 100)) formData.append('left', Math.round(positionObj[0].x)) formData.append('top', Math.round(positionObj[0].y)) console.log('🚀 ~ handleCanvasToPng ~ formData:', formData) // 이미지 크롭 요청 const result = await post({ url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/canvas`, data: formData, }) console.log('🚀 ~ handleCanvasToPng ~ result:', result) return result } catch (e) { setIsGlobalLoading(false) console.log('🚀 ~ handleCanvasToPng ~ e:', e) } } /** * 마우스 포인터의 가이드라인을 제거합니다. */ const removeMouseLines = () => { if (canvas?._objects.length > 0) { const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine') mouseLines.forEach((item) => canvas?.remove(item)) } canvas?.renderAll() } return { handleCanvasToPng } }