dev #285
@ -120,7 +120,44 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
const beforeCapture = (type) => {
|
const beforeCapture = (type) => {
|
||||||
setCanvasZoom(100)
|
setCanvasZoom(100)
|
||||||
canvas.set({ zoom: 1 })
|
canvas.set({ zoom: 1 })
|
||||||
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
|
||||||
|
// roof 객체들을 찾아서 중앙점 계산
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
|
||||||
|
|
||||||
|
if (roofs.length > 0) {
|
||||||
|
// 모든 roof의 x, y 좌표를 수집
|
||||||
|
const allPoints = []
|
||||||
|
roofs.forEach((roof) => {
|
||||||
|
if (roof.getCurrentPoints()) {
|
||||||
|
roof.getCurrentPoints().forEach((point) => {
|
||||||
|
allPoints.push({ x: point.x, y: point.y })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (allPoints.length > 0) {
|
||||||
|
// 모든 점들의 중앙값 계산
|
||||||
|
const minX = Math.min(...allPoints.map((p) => p.x))
|
||||||
|
const maxX = Math.max(...allPoints.map((p) => p.x))
|
||||||
|
const minY = Math.min(...allPoints.map((p) => p.y))
|
||||||
|
const maxY = Math.max(...allPoints.map((p) => p.y))
|
||||||
|
|
||||||
|
const centerX = (minX + maxX) / 2
|
||||||
|
const centerY = (minY + maxY) / 2
|
||||||
|
|
||||||
|
// 캔버스 중앙으로 이동하기 위한 오프셋 계산
|
||||||
|
const canvasWidth = canvas.getWidth()
|
||||||
|
const canvasHeight = canvas.getHeight()
|
||||||
|
const offsetX = canvasWidth / 2 - centerX
|
||||||
|
const offsetY = canvasHeight / 2 - centerY
|
||||||
|
|
||||||
|
canvas.viewportTransform = [1, 0, 0, 1, offsetX, offsetY]
|
||||||
|
} else {
|
||||||
|
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
||||||
|
}
|
||||||
|
|
||||||
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
const circuitNumberTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber')
|
const circuitNumberTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber')
|
||||||
@ -139,40 +176,9 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
// roof polygon들의 중간점 계산
|
// roof polygon들의 중간점 계산
|
||||||
const roofPolygons = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const roofPolygons = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
let x, y
|
let x, y
|
||||||
x = 0 //canvas.width / 2
|
x = canvas.width / 2
|
||||||
y = 1000 //canvas.height / 2
|
y = canvas.height / 2
|
||||||
|
|
||||||
/*if (roofPolygons.length > 0) {
|
|
||||||
let minX = Infinity,
|
|
||||||
minY = Infinity,
|
|
||||||
maxX = -Infinity,
|
|
||||||
maxY = -Infinity
|
|
||||||
|
|
||||||
roofPolygons.forEach((obj) => {
|
|
||||||
const boundingRect = obj.getBoundingRect()
|
|
||||||
minX = Math.min(minX, boundingRect.left)
|
|
||||||
minY = Math.min(minY, boundingRect.top)
|
|
||||||
maxX = Math.max(maxX, boundingRect.left + boundingRect.width)
|
|
||||||
maxY = Math.max(maxY, boundingRect.top + boundingRect.height)
|
|
||||||
})
|
|
||||||
|
|
||||||
x = (minX + maxX) / 2
|
|
||||||
y = (minY + maxY) / 2
|
|
||||||
} else {
|
|
||||||
// roof polygon이 없으면 기본 중앙점 사용
|
|
||||||
x = canvas.width / 2
|
|
||||||
y = canvas.height / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x > 1600) {
|
|
||||||
x = 0
|
|
||||||
y = 0
|
|
||||||
}
|
|
||||||
if (y > 1600) {
|
|
||||||
x = 0
|
|
||||||
y = 0
|
|
||||||
}*/
|
|
||||||
|
|
||||||
canvas.zoomToPoint(new fabric.Point(x, y), 0.4)
|
canvas.zoomToPoint(new fabric.Point(x, y), 0.4)
|
||||||
changeFontSize('lengthText', '28')
|
changeFontSize('lengthText', '28')
|
||||||
changeFontSize('circuitNumber', '28')
|
changeFontSize('circuitNumber', '28')
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useGrid } from '@/hooks/common/useGrid'
|
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
|
|
||||||
const GRID_PADDING = 5
|
const GRID_PADDING = 5
|
||||||
export default function GridCopy(props) {
|
export default function GridCopy(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
@ -25,10 +25,10 @@ export default function GridCopy(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const copy = (object, length) => {
|
const copy = (object, length) => {
|
||||||
const lineStartX = object.direction === 'vertical' ? object.x1 + length : 0
|
const lineStartX = object.direction === 'vertical' ? object.x1 + length : object.x1
|
||||||
const lineEndX = object.direction === 'vertical' ? object.x2 + length : canvas.width
|
const lineEndX = object.direction === 'vertical' ? object.x2 + length : object.x2
|
||||||
const lineStartY = object.direction === 'vertical' ? 0 : object.y1 + length
|
const lineStartY = object.direction === 'vertical' ? object.y1 : object.y1 + length
|
||||||
const lineEndY = object.direction === 'vertical' ? canvas.width : object.y1 + length
|
const lineEndY = object.direction === 'vertical' ? object.y2 : object.y1 + length
|
||||||
|
|
||||||
const line = new fabric.Line([lineStartX, lineStartY, lineEndX, lineEndY], {
|
const line = new fabric.Line([lineStartX, lineStartY, lineEndX, lineEndY], {
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
|
|||||||
@ -3,11 +3,9 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
|
||||||
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { set } from 'react-hook-form'
|
|
||||||
|
|
||||||
export default function GridMove(props) {
|
export default function GridMove(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
@ -70,10 +68,10 @@ export default function GridMove(props) {
|
|||||||
const move = (object, x, y) => {
|
const move = (object, x, y) => {
|
||||||
object.set({
|
object.set({
|
||||||
...object,
|
...object,
|
||||||
x1: object.direction === 'vertical' ? object.x1 + x : 0,
|
x1: object.direction === 'vertical' ? object.x1 + x : object.x1,
|
||||||
x2: object.direction === 'vertical' ? object.x1 + x : canvas.width,
|
x2: object.direction === 'vertical' ? object.x1 + x : object.x2,
|
||||||
y1: object.direction === 'vertical' ? 0 : object.y1 + y,
|
y1: object.direction === 'vertical' ? object.y1 : object.y1 + y,
|
||||||
y2: object.direction === 'vertical' ? canvas.height : object.y1 + y,
|
y2: object.direction === 'vertical' ? object.y2 : object.y1 + y,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { canvasState, dotLineGridSettingState } from '@/store/canvasAtom'
|
import { canvasState, canvasZoomState, dotLineGridSettingState } from '@/store/canvasAtom'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
|
|
||||||
const GRID_PADDING = 5
|
const GRID_PADDING = 5
|
||||||
|
|
||||||
export function useGrid() {
|
export function useGrid() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
const dotLineGridSetting = useRecoilValue(dotLineGridSettingState)
|
const dotLineGridSetting = useRecoilValue(dotLineGridSettingState)
|
||||||
const gridColor = useRecoilValue(gridColorState)
|
const gridColor = useRecoilValue(gridColorState)
|
||||||
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
||||||
|
const zoom = useRecoilValue(canvasZoomState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -90,14 +93,32 @@ export function useGrid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (patternData.lineGridDisplay) {
|
if (patternData.lineGridDisplay) {
|
||||||
for (let i = 0; i < 5000 / patternData.gridVertical + 1; i++) {
|
// 캔버스의 실제 보이는 영역 계산
|
||||||
|
const canvasWidth = canvas.getWidth()
|
||||||
|
const canvasHeight = canvas.getHeight()
|
||||||
|
const currentZoom = canvas.getZoom()
|
||||||
|
const viewportTransform = canvas.viewportTransform
|
||||||
|
|
||||||
|
const visibleLeft = -viewportTransform[4] / currentZoom
|
||||||
|
const visibleTop = -viewportTransform[5] / currentZoom
|
||||||
|
const visibleRight = visibleLeft + canvasWidth / currentZoom
|
||||||
|
const visibleBottom = visibleTop + canvasHeight / currentZoom
|
||||||
|
|
||||||
|
// 여유 공간 추가
|
||||||
|
const padding = 200
|
||||||
|
const gridLeft = visibleLeft - padding
|
||||||
|
const gridTop = visibleTop - padding
|
||||||
|
const gridRight = visibleRight + padding
|
||||||
|
const gridBottom = visibleBottom + padding
|
||||||
|
|
||||||
|
// 가로선 생성 (수평선)
|
||||||
|
const horizontalGridRange = gridBottom - gridTop
|
||||||
|
const horizontalGridCount = Math.ceil(horizontalGridRange / patternData.gridVertical) + 2
|
||||||
|
|
||||||
|
for (let i = 0; i < horizontalGridCount; i++) {
|
||||||
|
const y = gridTop + i * patternData.gridVertical
|
||||||
const horizontalLine = new fabric.Line(
|
const horizontalLine = new fabric.Line(
|
||||||
[
|
[gridLeft, y, gridRight, y],
|
||||||
-1500,
|
|
||||||
-1500 + i * patternData.gridVertical - patternData.gridVertical / 2,
|
|
||||||
3000,
|
|
||||||
-1500 + i * patternData.gridVertical - patternData.gridVertical / 2,
|
|
||||||
],
|
|
||||||
{
|
{
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@ -118,14 +139,14 @@ export function useGrid() {
|
|||||||
canvas.add(horizontalLine)
|
canvas.add(horizontalLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < 5000 / patternData.gridHorizon + 1; i++) {
|
// 세로선 생성 (수직선)
|
||||||
|
const verticalGridRange = gridRight - gridLeft
|
||||||
|
const verticalGridCount = Math.ceil(verticalGridRange / patternData.gridHorizon) + 2
|
||||||
|
|
||||||
|
for (let i = 0; i < verticalGridCount; i++) {
|
||||||
|
const x = gridLeft + i * patternData.gridHorizon
|
||||||
const verticalLine = new fabric.Line(
|
const verticalLine = new fabric.Line(
|
||||||
[
|
[x, gridTop, x, gridBottom],
|
||||||
-1500 + i * patternData.gridHorizon - patternData.gridHorizon / 2,
|
|
||||||
-1500,
|
|
||||||
-1500 + i * patternData.gridHorizon - patternData.gridHorizon / 2,
|
|
||||||
3000,
|
|
||||||
],
|
|
||||||
{
|
{
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@ -148,7 +169,7 @@ export function useGrid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}, [dotLineGridSetting])
|
}, [dotLineGridSetting, zoom])
|
||||||
|
|
||||||
const move = (object, x, y) => {
|
const move = (object, x, y) => {
|
||||||
object.set({
|
object.set({
|
||||||
|
|||||||
@ -1,29 +1,29 @@
|
|||||||
import { useEffect, useState, useRef, useContext } from 'react'
|
import { useContext, useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import {
|
import {
|
||||||
adsorptionPointModeState,
|
adsorptionPointModeState,
|
||||||
adsorptionRangeState,
|
adsorptionRangeState,
|
||||||
canvasState,
|
|
||||||
planSizeSettingState,
|
|
||||||
dotLineGridSettingState,
|
|
||||||
canvasSettingState,
|
canvasSettingState,
|
||||||
|
canvasState,
|
||||||
currentMenuState,
|
currentMenuState,
|
||||||
|
dotLineGridSettingState,
|
||||||
|
planSizeSettingState,
|
||||||
} from '@/store/canvasAtom'
|
} from '@/store/canvasAtom'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import {
|
import {
|
||||||
|
addedRoofsState,
|
||||||
|
basicSettingState,
|
||||||
correntObjectNoState,
|
correntObjectNoState,
|
||||||
corridorDimensionSelector,
|
corridorDimensionSelector,
|
||||||
settingModalFirstOptionsState,
|
fetchRoofMaterialsState,
|
||||||
settingModalSecondOptionsState,
|
|
||||||
settingModalGridOptionsState,
|
|
||||||
basicSettingState,
|
|
||||||
roofMaterialsAtom,
|
roofMaterialsAtom,
|
||||||
selectedRoofMaterialSelector,
|
selectedRoofMaterialSelector,
|
||||||
addedRoofsState,
|
settingModalFirstOptionsState,
|
||||||
fetchRoofMaterialsState,
|
settingModalGridOptionsState,
|
||||||
|
settingModalSecondOptionsState,
|
||||||
} from '@/store/settingAtom'
|
} from '@/store/settingAtom'
|
||||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||||
import { globalFontAtom } from '@/store/fontAtom'
|
import { globalFontAtom } from '@/store/fontAtom'
|
||||||
@ -339,11 +339,11 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
*/
|
*/
|
||||||
const fetchBasicSettings = async (planNo, openPoint) => {
|
const fetchBasicSettings = async (planNo, openPoint) => {
|
||||||
// 지붕재 데이터가 없으면 먼저 로드
|
// 지붕재 데이터가 없으면 먼저 로드
|
||||||
let materials = roofMaterials;
|
let materials = roofMaterials
|
||||||
if (!materials || materials.length === 0) {
|
if (!materials || materials.length === 0) {
|
||||||
logger.log("Waiting for roofMaterials to be loaded...");
|
logger.log('Waiting for roofMaterials to be loaded...')
|
||||||
materials = await addRoofMaterials();
|
materials = await addRoofMaterials()
|
||||||
logger.log("roofMaterials loaded:", materials);
|
logger.log('roofMaterials loaded:', materials)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -529,8 +529,14 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
? params.selectedRoofMaterial.raftBaseCd
|
? params.selectedRoofMaterial.raftBaseCd
|
||||||
: params.roofsData.raft,
|
: params.roofsData.raft,
|
||||||
roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout,
|
roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout,
|
||||||
roofPitch: params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined || params.roofsData.roofPitch === '' ? 0 : params.roofsData.roofPitch,
|
roofPitch:
|
||||||
roofAngle: params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined || params.roofsData.roofAngle === '' ? 0 : params.roofsData.roofAngle,
|
params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined || params.roofsData.roofPitch === ''
|
||||||
|
? 0
|
||||||
|
: params.roofsData.roofPitch,
|
||||||
|
roofAngle:
|
||||||
|
params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined || params.roofsData.roofAngle === ''
|
||||||
|
? 0
|
||||||
|
: params.roofsData.roofAngle,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@ -643,7 +649,11 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
|
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
|
||||||
|
|
||||||
/** 도면크기 설정 */
|
/** 도면크기 설정 */
|
||||||
setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical })
|
setPlanSizeSettingMode({
|
||||||
|
...planSizeSettingMode,
|
||||||
|
originHorizon: res.originHorizon,
|
||||||
|
originVertical: res.originVertical,
|
||||||
|
})
|
||||||
canvas.setWidth(res.originHorizon)
|
canvas.setWidth(res.originHorizon)
|
||||||
canvas.setHeight(res.originVertical)
|
canvas.setHeight(res.originVertical)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
@ -723,7 +733,7 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
/** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */
|
/** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */
|
||||||
|
|
||||||
/** 흡착점 ON/OFF */
|
/** 흡착점 ON/OFF */
|
||||||
setAdsorptionPointMode(false)
|
setAdsorptionPointMode(true)
|
||||||
|
|
||||||
/** 치수선 설정 */
|
/** 치수선 설정 */
|
||||||
resetDimensionLineSettings()
|
resetDimensionLineSettings()
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export function useCanvas(id) {
|
|||||||
const isImageDisplay = useRecoilValue(imageDisplaySelector)
|
const isImageDisplay = useRecoilValue(imageDisplaySelector)
|
||||||
const {} = useFont()
|
const {} = useFont()
|
||||||
const resetCanvasZoom = useResetRecoilState(canvasZoomState)
|
const resetCanvasZoom = useResetRecoilState(canvasZoomState)
|
||||||
|
const zoom = useRecoilValue(canvasZoomState)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 처음 셋팅
|
* 처음 셋팅
|
||||||
@ -50,8 +51,53 @@ export function useCanvas(id) {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// canvas 사이즈가 변경되면 다시
|
// zoom 상태가 변경될 때 tempGrid 라인들의 크기를 캔버스에 맞게 조정
|
||||||
}, [canvasSize])
|
if (canvas) {
|
||||||
|
adjustTempGridLines()
|
||||||
|
}
|
||||||
|
}, [zoom])
|
||||||
|
|
||||||
|
const adjustTempGridLines = () => {
|
||||||
|
if (!canvas) return
|
||||||
|
|
||||||
|
const canvasWidth = canvas.getWidth()
|
||||||
|
const canvasHeight = canvas.getHeight()
|
||||||
|
const currentZoom = canvas.getZoom()
|
||||||
|
const viewportTransform = canvas.viewportTransform
|
||||||
|
|
||||||
|
// 실제 보이는 캔버스 영역 계산 (zoom과 pan 고려)
|
||||||
|
const visibleLeft = -viewportTransform[4] / currentZoom
|
||||||
|
const visibleTop = -viewportTransform[5] / currentZoom
|
||||||
|
const visibleRight = visibleLeft + canvasWidth / currentZoom
|
||||||
|
const visibleBottom = visibleTop + canvasHeight / currentZoom
|
||||||
|
|
||||||
|
// tempGrid 라인들을 찾아서 크기 조정
|
||||||
|
const tempGridLines = canvas.getObjects().filter((obj) => ['tempGrid', 'lineGrid', 'mouseLine'].includes(obj.name))
|
||||||
|
|
||||||
|
tempGridLines.forEach((line) => {
|
||||||
|
if (line.direction === 'vertical') {
|
||||||
|
// 세로 라인: y축을 캔버스 전체 높이로 설정
|
||||||
|
line.set({
|
||||||
|
x1: line.x1,
|
||||||
|
y1: visibleTop - 100, // 여유 공간 추가
|
||||||
|
x2: line.x1,
|
||||||
|
y2: visibleBottom + 100, // 여유 공간 추가
|
||||||
|
})
|
||||||
|
} else if (line.direction === 'horizontal') {
|
||||||
|
// 가로 라인: x축을 캔버스 전체 너비로 설정
|
||||||
|
line.set({
|
||||||
|
x1: visibleLeft - 100, // 여유 공간 추가
|
||||||
|
y1: line.y1,
|
||||||
|
x2: visibleRight + 100, // 여유 공간 추가
|
||||||
|
y2: line.y1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
line.setCoords()
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
canvas
|
canvas
|
||||||
|
|||||||
@ -369,18 +369,39 @@ export function useEvent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const drawMouseLine = (pointer) => {
|
const drawMouseLine = (pointer) => {
|
||||||
const horizontalLine = new fabric.Line([-2 * canvas.width, pointer.y, 2 * canvas.width, pointer.y], {
|
// 캔버스의 실제 보이는 영역 계산 (zoom과 pan 고려)
|
||||||
|
const canvasWidth = canvas.getWidth()
|
||||||
|
const canvasHeight = canvas.getHeight()
|
||||||
|
const currentZoom = canvas.getZoom()
|
||||||
|
const viewportTransform = canvas.viewportTransform
|
||||||
|
|
||||||
|
const visibleLeft = -viewportTransform[4] / currentZoom
|
||||||
|
const visibleTop = -viewportTransform[5] / currentZoom
|
||||||
|
const visibleRight = visibleLeft + canvasWidth / currentZoom
|
||||||
|
const visibleBottom = visibleTop + canvasHeight / currentZoom
|
||||||
|
|
||||||
|
// 여유 공간 추가
|
||||||
|
const padding = 200
|
||||||
|
const lineLeft = visibleLeft - padding
|
||||||
|
const lineTop = visibleTop - padding
|
||||||
|
const lineRight = visibleRight + padding
|
||||||
|
const lineBottom = visibleBottom + padding
|
||||||
|
|
||||||
|
// 가로선 (수평선)
|
||||||
|
const horizontalLine = new fabric.Line([lineLeft, pointer.y, lineRight, pointer.y], {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
direction: 'horizontal',
|
||||||
name: 'mouseLine',
|
name: 'mouseLine',
|
||||||
})
|
})
|
||||||
|
|
||||||
// 세로선
|
// 세로선 (수직선)
|
||||||
const verticalLine = new fabric.Line([pointer.x, -2 * canvas.height, pointer.x, 2 * canvas.height], {
|
const verticalLine = new fabric.Line([pointer.x, lineTop, pointer.x, lineBottom], {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
direction: 'vertical',
|
||||||
name: 'mouseLine',
|
name: 'mouseLine',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user