줌 확대, 축소 시 오브젝트 선택 안되는 현상 수정

This commit is contained in:
hyojun.choi 2025-07-09 16:02:55 +09:00 committed by ysCha
parent 71d92f12b8
commit 0badbef52c
3 changed files with 87 additions and 19 deletions

View File

@ -183,29 +183,64 @@ export const QLine = fabric.util.createClass(fabric.Line, {
return this
},
containsPoint: function(point) {
setCoords: function () {
// 부모 클래스의 setCoords 호출
this.callSuper('setCoords')
// QLine의 경우 추가 처리 - 항상 강제로 재계산
if (this.canvas) {
// 모든 좌표 관련 캐시 초기화
delete this.oCoords
delete this.aCoords
delete this.__corner
// 다시 부모 setCoords 호출
this.callSuper('setCoords')
// 한 번 더 강제로 bounding rect 재계산
this._clearCache && this._clearCache()
}
},
containsPoint: function (point) {
// 먼저 좌표 업데이트
this.setCoords()
// 캔버스 줌과 viewport transform 고려한 좌표 변환
let localPoint = point
if (this.canvas) {
const vpt = this.canvas.viewportTransform
if (vpt) {
// viewport transform 역변환
const inverted = fabric.util.invertTransform(vpt)
localPoint = fabric.util.transformPoint(point, inverted)
}
}
// 기본 boundingRect 사용하되 줌을 고려하여 선택 영역 조정
const boundingRect = this.getBoundingRect(true)
// 선의 방향 판단
const dx = Math.abs(this.x2 - this.x1)
const dy = Math.abs(this.y2 - this.y1)
const isVertical = dx < dy && dx < 10 // 세로선 (가로 변화가 작음)
const isDiagonal = dx > 10 && dy > 10 // 대각선 (가로, 세로 모두 변화)
const isVertical = dx < dy && dx < 10
const isDiagonal = dx > 10 && dy > 10
// 줌 레벨에 따른 선택 영역 조정
const zoom = this.canvas ? this.canvas.getZoom() : 1
const baseMultiplier = 1 // 줌이 클수록 선택 영역을 줄임
let reducedWidth, reducedHeight
if (isDiagonal) {
// 대각선의 경우: 1/2 크기
reducedWidth = boundingRect.width / 2
reducedHeight = boundingRect.height / 2
reducedWidth = Math.max(boundingRect.width / 2, 10 * baseMultiplier)
reducedHeight = Math.max(boundingRect.height / 2, 10 * baseMultiplier)
} else if (isVertical) {
// 세로선의 경우: 가로 선택범위 2배
reducedWidth = boundingRect.width * 2
reducedHeight = boundingRect.height / 3
reducedWidth = Math.max(boundingRect.width * 2, 20 * baseMultiplier)
reducedHeight = boundingRect.height
} else {
// 가로선의 경우: 세로 선택범위 2배
reducedWidth = boundingRect.width / 3
reducedHeight = boundingRect.height * 2
reducedWidth = boundingRect.width
reducedHeight = Math.max(boundingRect.height * 2, 20 * baseMultiplier)
}
// 축소된 영역의 중심점 계산
@ -219,9 +254,6 @@ export const QLine = fabric.util.createClass(fabric.Line, {
const bottom = centerY + reducedHeight / 2
// 점이 축소된 영역 내에 있는지 확인
return point.x >= left &&
point.x <= right &&
point.y >= top &&
point.y <= bottom
return localPoint.x >= left && localPoint.x <= right && localPoint.y >= top && localPoint.y <= bottom
},
})

View File

@ -689,13 +689,46 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
return intersects % 2 === 1
},
setCoords: function () {
// 부모 클래스의 setCoords 호출
this.callSuper('setCoords')
// QPolygon의 경우 추가 처리 - 항상 강제로 재계산
if (this.canvas) {
// 모든 좌표 관련 캐시 초기화
delete this.oCoords
delete this.aCoords
delete this.__corner
// 다시 부모 setCoords 호출
this.callSuper('setCoords')
// 한 번 더 강제로 bounding rect 재계산
this._clearCache && this._clearCache()
}
},
containsPoint: function (point) {
// 먼저 좌표 업데이트
this.setCoords()
// 캔버스 줌과 viewport transform 고려한 좌표 변환
let localPoint = point
if (this.canvas) {
const vpt = this.canvas.viewportTransform
if (vpt) {
// viewport transform 역변환
const inverted = fabric.util.invertTransform(vpt)
localPoint = fabric.util.transformPoint(point, inverted)
}
}
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
const isInside = this.inPolygon(point)
const isInside = this.inPolygon(localPoint)
this.set('selectable', isInside)
return isInside
} else {
return this.callSuper('containsPoint', point)
return this.callSuper('containsPoint', localPoint)
}
},

View File

@ -16,7 +16,6 @@ import { useTempGrid } from '@/hooks/useTempGrid'
import { gridColorState } from '@/store/gridAtom'
import { gridDisplaySelector } from '@/store/settingAtom'
import { MENU, POLYGON_TYPE } from '@/common/common'
import useMenu from '@/hooks/common/useMenu'
export function useEvent() {
const canvas = useRecoilValue(canvasState)
@ -105,6 +104,10 @@ export function useEvent() {
canvas.setViewportTransform(canvas.viewportTransform)
canvas.requestRenderAll()
canvas.getObjects().forEach((obj) => {
obj.setCoords()
})
// 이벤트의 기본 동작 방지 (스크롤 방지)
opt.e.preventDefault()
opt.e.stopPropagation()