dev #223

Merged
ysCha merged 4 commits from dev into prd-deploy 2025-07-21 15:37:13 +09:00
4 changed files with 55 additions and 55 deletions

View File

@ -81,44 +81,35 @@ const cropImage = async (Key, width, height, left, top) => {
}
}
//크롭된 이미지를 가지고 높이 기준 -> 너비 기준으로 비율 변경 후 이미지에 추가
//크롭된 이미지를 배경 크기에 맞게 리사이즈
const resizeImage = async (image) => {
// //이미지를 cm로 변환
let imageHeightCm = Math.round((image.bitmap.height * 2.54) / 96) //원본 이미지 센치로 변환
let imageWidthCm = Math.round((image.bitmap.width * 2.54) / 96) //원본 이미지 센치로 변환
const calcWidthRatio = 12.89 / imageHeightCm //원본 비율 계산
let convertHeightCm = Math.round(imageHeightCm * calcWidthRatio) //변환된 이미지 CM
let convertWidthCm = Math.round(imageWidthCm * calcWidthRatio) //변환된 이미지 CM
let convertHeightBitmap = Math.round((convertHeightCm * 96) / 2.54) //비트맵 사이즈로 변환
let convertWidthBitmap = Math.round((convertWidthCm * 96) / 2.54) //비트맵 사이즈로 변환
//높이 기준으로 리사이즈를 함
image.resize({ w: convertWidthBitmap, h: convertHeightBitmap, mode: Jimp.RESIZE_BILINEAR })
//높이를 기준으로 변경 후에 가로 폭이 더 넓으면 가로폭 기준으로 다시 사이즈를 조절한다
if (convertWidthCm > 35.4) {
//너비가 더 클때
imageHeightCm = Math.round((image.bitmap.height * 2.54) / 96) //높이 기준으로 리사이즈된 이미지 크기
imageWidthCm = Math.round((image.bitmap.width * 2.54) / 96) //높이 기준으로 리사이즈된 이미지 크기
const calcWidthRatio = 35.4 / imageWidthCm //리사이즈된 이미지 가로 비율 계산
convertHeightCm = Math.round(imageHeightCm * calcWidthRatio) //너비 기준 이미지 비율 계산
convertWidthCm = Math.round(imageWidthCm * calcWidthRatio) //변환된 이미지 CM
convertHeightBitmap = Math.round((convertHeightCm * 96) / 2.54) //비트맵 사이즈로 변환
convertWidthBitmap = Math.round((convertWidthCm * 96) / 2.54) //비트맵 사이즈로 변환
image.resize({ w: convertWidthBitmap, h: convertHeightBitmap, mode: Jimp.RESIZE_BILINEAR }) //이미지 리사이즈
}
//엑셀 템플릿 너비 35.4cm, 높이 12.89cm
const convertStandardWidth = Math.round((35.4 * 96) / 2.54)
const convertStandardHeight = Math.round((12.89 * 96) / 2.54)
//엑셀 템플릿 사이즈로 배경 이미지를 생성
// 이미지를 배경의 98%까지 확대 (훨씬 더 크게)
const targetImageWidth = convertStandardWidth * 0.98
const targetImageHeight = convertStandardHeight * 0.98
const scaleX = targetImageWidth / image.bitmap.width
const scaleY = targetImageHeight / image.bitmap.height
let scale = Math.min(scaleX, scaleY) // 비율 유지하면서 최대한 크게
// scale 저장 (나중에 전체 확대에 사용)
const originalScale = scale
let finalWidth = Math.round(image.bitmap.width * scale)
let finalHeight = Math.round(image.bitmap.height * scale)
if (scale < 0.6) {
finalWidth = targetImageWidth
finalHeight = targetImageHeight
}
// 실제 리사이즈 실행
image.resize({ w: finalWidth, h: finalHeight })
//배경 이미지를 생성
const mixedImage = new Jimp({ width: convertStandardWidth, height: convertStandardHeight, color: 0xffffffff })
//이미지를 중앙에 배치
@ -127,11 +118,19 @@ const resizeImage = async (image) => {
//이미지를 배경 이미지에 합성
mixedImage.composite(image, x, y, {
mode: Jimp.BLEND_SOURCE_OVER,
opacitySource: 1, // 원본 투명도 유지
opacityDest: 1,
})
// scale이 0.8 이하인 경우 완성된 이미지를 전체적으로 확대
if (originalScale <= 0.8) {
const enlargeRatio = 1.5 // 25% 확대
const newWidth = Math.round(mixedImage.bitmap.width * enlargeRatio)
const newHeight = Math.round(mixedImage.bitmap.height * enlargeRatio)
mixedImage.resize({ w: newWidth, h: newHeight })
}
return mixedImage
}

View File

@ -239,11 +239,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
/* innerLines 초기화 */
this.canvas
.getObjects()
.filter((obj) => obj.parentId === this.id && obj.name !== POLYGON_TYPE.WALL && obj.name !== POLYGON_TYPE.ROOF)
.filter(
(obj) =>
obj.parentId === this.id &&
obj.name !== POLYGON_TYPE.WALL &&
obj.name !== POLYGON_TYPE.ROOF &&
obj.name !== 'outerLine' &&
obj.name !== 'baseLine',
// && obj.name !== 'outerLinePoint',
)
.forEach((obj) => this.canvas.remove(obj))
/*this.innerLines.forEach((line) => {
this.canvas.remove(line)
})*/
this.canvas.renderAll()
let textMode = 'plane'

View File

@ -1,16 +1,13 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useState, useEffect, useContext, useRef } from 'react'
import { useContext, useEffect, useRef, useState } from 'react'
import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect'
import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import PassivityCircuitAllocation from './step/type/PassivityCircuitAllocation'
import { useMasterController } from '@/hooks/common/useMasterController'
import { correntObjectNoState } from '@/store/settingAtom'
import { useRecoilValue } from 'recoil'
import { useRecoilState, useRecoilValue } from 'recoil'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { useRecoilState } from 'recoil'
import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom'
import { POLYGON_TYPE } from '@/common/common'
import { useSwal } from '@/hooks/useSwal'
import { canvasState, canvasZoomState } from '@/store/canvasAtom'
@ -21,9 +18,7 @@ import { v4 as uuidv4 } from 'uuid'
import { useEstimate } from '@/hooks/useEstimate'
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
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'
@ -107,10 +102,10 @@ export default function CircuitTrestleSetting({ id }) {
}
}, [])
const capture = (type) => {
const capture = async (type) => {
beforeCapture()
handleCanvasToPng(type)
await handleCanvasToPng(type)
afterCapture()
@ -123,20 +118,15 @@ export default function CircuitTrestleSetting({ id }) {
//
const beforeCapture = () => {
// setCanvasZoom(100)
const arrows = canvas.getObjects().filter((obj) => obj.name === 'arrow')
setCanvasZoom(100)
canvas.set({ zoom: 1 })
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
let x, y
x = canvas.width / 2
y = canvas.height / 2
// 0,0 50%
if (arrows.some((arrow) => arrow.left < 0) || arrows.some((arrow) => arrow.top < 0)) {
x = 0
y = 0
}
canvas.zoomToPoint(new fabric.Point(x, y), 0.5)
changeFontSize('lengthText', '28')
changeFontSize('circuitNumber', '28')

View File

@ -833,12 +833,17 @@ export const usePolygon = () => {
return !(range1.max < range2.min || range2.max < range1.min)
}
polygonLines.forEach((line) => {
line.need = true
})
// innerLines와 polygonLines의 겹침을 확인하고 type 변경
innerLines.forEach((innerLine) => {
polygonLines.forEach((polygonLine) => {
if (checkLineOverlap(innerLine, polygonLine)) {
// innerLine의 type을 polygonLine의 type으로 변경
if (polygonLine.attributes?.type && innerLine.attributes) {
polygonLine.need = false
innerLine.attributes.type = polygonLine.attributes.type
}
}
@ -846,6 +851,7 @@ export const usePolygon = () => {
})
const roofs = []
polygonLines = polygonLines.filter((line) => line.need)
//polygonLines를 순회하며 innerLines와 교차하는 점을 line의 속성에 배열로 저장한다.
polygonLines.forEach((line) => {