107 lines
3.8 KiB
JavaScript
107 lines
3.8 KiB
JavaScript
import { useRecoilValue } from 'recoil'
|
|
import { canvasState } from '@/store/canvasAtom'
|
|
import { useAxios } from '../useAxios'
|
|
import { usePlan } from '../usePlan'
|
|
import { POLYGON_TYPE } from '@/common/common'
|
|
import { QcastContext } from '@/app/QcastProvider'
|
|
import { useContext } from 'react'
|
|
|
|
/**
|
|
* 이미지 로더 hook
|
|
* 캔버스를 바이너리로 변환하고 이미지 객체에 붙여서 다시 이미지를 바이너리로 전달
|
|
* 캔버스 데이터가 바이너리로 변경되면 용량이 너무 커서 post전송에 실패할 수 있음
|
|
* @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 : acc), 0)
|
|
const maxY = objects.reduce((acc, cur) => (cur.top + cur.height > acc ? cur.top : 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)
|
|
/** 이미지 크롭 좌표 계산 */
|
|
const positionObj = getImageCoordinates()
|
|
console.log('🚀 ~ handleCanvasToPng ~ positionObj:', positionObj)
|
|
formData.append('width', Math.round(positionObj[1].x - positionObj[0].x + 100))
|
|
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 }
|
|
}
|