diff --git a/package.json b/package.json index 792ddde9..14b1299b 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "framer-motion": "^11.2.13", "fs": "^0.0.1-security", "iron-session": "^8.0.2", + "jimp": "^1.6.0", "js-cookie": "^3.0.5", "mathjs": "^13.0.2", "mssql": "^11.0.1", diff --git a/src/app/api/image/canvas/route.js b/src/app/api/image/canvas/route.js index 77d1c95c..2a20da92 100644 --- a/src/app/api/image/canvas/route.js +++ b/src/app/api/image/canvas/route.js @@ -1,7 +1,8 @@ import { NextResponse } from 'next/server' -import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3' -import sharp from 'sharp' +import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3' import { v4 as uuidv4 } from 'uuid' +import { Jimp } from 'jimp' + const Bucket = process.env.AMPLIFY_BUCKET const s3 = new S3Client({ region: process.env.AWS_REGION, @@ -23,8 +24,6 @@ const checkArea = (obj) => { const cropImage = async (Key, width, height, left, top) => { try { - const checkResult = checkArea({ width, height, left, top }) - // Get the image from S3 const { Body } = await s3.send( new GetObjectCommand({ @@ -33,28 +32,45 @@ const cropImage = async (Key, width, height, left, top) => { }), ) - // Convert stream to buffer const chunks = [] for await (const chunk of Body) { chunks.push(chunk) } - const imageBuffer = Buffer.concat(chunks) + const buffer = Buffer.concat(chunks) - let processedImage - if (!checkResult) { - processedImage = await sharp(imageBuffer).toBuffer() - } else { - processedImage = await sharp(imageBuffer) - .extract({ - width: parseInt(width), - height: parseInt(height), - left: parseInt(left), - top: parseInt(top), - }) - .png() - .toBuffer() - } - return processedImage + const image = await Jimp.read(buffer) + + image.autocrop({ tolerance: 0.0002, leaveBorder: 10 }) + return await image.getBuffer('image/png') + + // Convert stream to buffer + // const chunks = [] + // for await (const chunk of Body) { + // chunks.push(chunk) + // } + // const imageBuffer = Buffer.concat(chunks) + + // const image = await Jimp.read(Body) + + // if (!checkResult) { + // processedImage = await image.toBuffer() + // } + + //let processedImage + // if (!checkResult) { + // processedImage = await sharp(imageBuffer).toBuffer() + // } else { + // processedImage = await sharp(imageBuffer) + // .extract({ + // width: parseInt(width), + // height: parseInt(height), + // left: parseInt(left), + // top: parseInt(top), + // }) + // .png() + // .toBuffer() + // } + // return processedImage } catch (error) { console.error('Error processing image:', error) throw error diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index f4972c54..d8ae2084 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -25,6 +25,8 @@ import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupSta import { useImgLoader } from '@/hooks/floorPlan/useImgLoader' import { usePlan } from '@/hooks/usePlan' import { QcastContext } from '@/app/QcastProvider' +import { fabric } from 'fabric' +import { fontSelector } from '@/store/fontAtom' const ALLOCATION_TYPE = { AUTO: 'auto', @@ -44,6 +46,9 @@ export default function CircuitTrestleSetting({ id }) { const { managementState, setManagementState } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController() + const flowText = useRecoilValue(fontSelector('flowText')) + const lengthText = useRecoilValue(fontSelector('lengthText')) + const circuitNumberText = useRecoilValue(fontSelector('circuitNumberText')) // 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가 const [selectedStepUpValues, setSelectedStepUpValues] = useState({}) @@ -102,10 +107,26 @@ export default function CircuitTrestleSetting({ id }) { } }, []) - const handleZoomClear = () => { + // 캡쳐 전 처리 + const beforeCapture = () => { + // setCanvasZoom(100) + const x = canvas.width / 2 + const y = canvas.height / 2 + canvas.zoomToPoint(new fabric.Point(x, y), 0.5) + changeFontSize('lengthText', '28') + changeFontSize('circuitNumber', '28') + changeFontSize('flowText', '28') + canvas.renderAll() + } + + // 캡쳐 후 처리 + const afterCapture = () => { setCanvasZoom(100) canvas.set({ zoom: 1 }) canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + changeFontSize('lengthText', lengthText.fontSize.value) + changeFontSize('circuitNumber', circuitNumberText.fontSize.value) + changeFontSize('flowText', flowText.fontSize.value) canvas.renderAll() } @@ -350,7 +371,7 @@ export default function CircuitTrestleSetting({ id }) { // 회로할당(승압설정) 저장 버튼 클릭 시 const onApply = async () => { - handleZoomClear() + beforeCapture() setAllModuleSurfaceIsComplete(false) setIsGlobalLoading(true) @@ -361,12 +382,9 @@ export default function CircuitTrestleSetting({ id }) { obj.pcses = getStepUpListData() }) - setViewCircuitNumberTexts(false) - handleCanvasToPng(1) //회로할당 저장 시 result=null인 경우에도 회로번호 텍스트 표시 유지 처리 - setViewCircuitNumberTexts(true) // 회로할당 저장 클릭 시 // 가대 및 지지금구 설치 @@ -382,6 +400,7 @@ export default function CircuitTrestleSetting({ id }) { if (result) { handleCanvasToPng(2) + afterCapture() // 견적서 저장 await saveEstimate(result) } else { @@ -391,6 +410,16 @@ export default function CircuitTrestleSetting({ id }) { // removeNotAllocationModules() } + const changeFontSize = (name, size) => { + const textObjs = canvas?.getObjects().filter((obj) => obj.name === name) + textObjs.forEach((obj) => { + obj.set({ + fontSize: size, + }) + }) + canvas.renderAll() + } + // 이전 버튼 클릭 시 const onClickPrev = () => { // setAllocationType(ALLOCATION_TYPE.AUTO) diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 5fbc3ab3..53d1956b 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -314,7 +314,8 @@ export function useRoofAllocationSetting(id) { setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true) drawDirectionArrow(currentObject) modifyModuleSelectionData() - closeAll() + // closeAll() + closePopup(id) basicSettingSave() setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList }) }