이벤트 위치 수정

This commit is contained in:
hyojun.choi 2024-08-26 11:14:09 +09:00
parent 89f117c230
commit 1494082df1
4 changed files with 138 additions and 155 deletions

View File

@ -11,6 +11,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
direction: null, direction: null,
idx: 0, idx: 0,
area: 0, area: 0,
children: [],
initialize: function (points, options, canvas) { initialize: function (points, options, canvas) {
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? false }) this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? false })
if (options.id) { if (options.id) {
@ -122,6 +123,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
lockRotation: true, lockRotation: true,
lockScalingX: true, lockScalingX: true,
lockScalingY: true, lockScalingY: true,
parent: this,
name: 'lengthText', name: 'lengthText',
}) })

View File

@ -17,6 +17,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
cells: [], cells: [],
parentId: null, parentId: null,
innerLines: [], innerLines: [],
children: [],
initialize: function (points, options, canvas) { initialize: function (points, options, canvas) {
// 소수점 전부 제거 // 소수점 전부 제거
points.forEach((point) => { points.forEach((point) => {
@ -195,6 +196,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
lockScalingY: true, lockScalingY: true,
idx: i, idx: i,
name: 'lengthText', name: 'lengthText',
parent: this,
}) })
this.texts.push(text) this.texts.push(text)
@ -271,6 +273,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
name: 'cell', name: 'cell',
idx: idx, idx: idx,
parentId: this.id, parentId: this.id,
parent: this,
}) })
idx++ idx++

View File

@ -179,25 +179,6 @@ export function useCanvas(id) {
}) })
} }
/**
* 선택한 도형을 삭제한다.
*/
const handleDelete = () => {
const targets = canvas?.getActiveObjects()
if (targets?.length === 0) {
alert('삭제할 대상을 선택해주세요.')
return
}
if (!confirm('정말로 삭제하시겠습니까?')) {
return
}
targets?.forEach((target) => {
canvas?.remove(target)
})
}
/** /**
* 페이지 캔버스 저장 * 페이지 캔버스 저장
* todo : 현재는 localStorage에 그냥 저장하지만 나중에 변경해야함 * todo : 현재는 localStorage에 그냥 저장하지만 나중에 변경해야함
@ -469,7 +450,6 @@ export function useCanvas(id) {
handleUndo, handleUndo,
handleRedo, handleRedo,
handleCopy, handleCopy,
handleDelete,
handleSave, handleSave,
handlePaste, handlePaste,
handleRotate, handleRotate,

View File

@ -12,16 +12,112 @@ export function useCanvasEvent() {
// 기본적인 이벤트 필요시 추가 // 기본적인 이벤트 필요시 추가
const attachDefaultEventOnCanvas = () => { const attachDefaultEventOnCanvas = () => {
removeEventOnCanvas() removeEventOnCanvas()
canvas?.on('object:added', onChange) canvas?.on('object:added', objectEvent.onChange)
canvas?.on('object:added', addEventOnObject) canvas?.on('object:added', objectEvent.addEvent)
canvas?.on('object:modified', onChange) canvas?.on('object:modified', objectEvent.onChange)
canvas?.on('object:removed', onChange) canvas?.on('object:removed', objectEvent.onChange)
canvas?.on('selection:cleared', selectionEvent.cleared) canvas?.on('selection:cleared', selectionEvent.cleared)
canvas?.on('selection:created', selectionEvent.created) canvas?.on('selection:created', selectionEvent.created)
canvas?.on('selection:updated', selectionEvent.updated) canvas?.on('selection:updated', selectionEvent.updated)
canvas?.on('object:added', () => { canvas?.on('object:added', () => {
document.addEventListener('keydown', handleKeyDown) document.addEventListener('keydown', handleKeyDown)
}) })
canvas?.on('object:removed', objectEvent.removed)
}
const objectEvent = {
onChange: (e) => {
const target = e.target
if (target) {
// settleDown(target)
}
},
addEvent: (e) => {
const target = e.target
if (target.type === 'QPolygon' || target.type === 'QLine') {
const textObjs = canvas?.getObjects().filter((obj) => obj.name === 'lengthText')
textObjs.forEach((obj) => {
obj.bringToFront()
})
}
if (target.name === 'cell') {
target.on('mousedown', () => {
if (target.get('selected')) {
target.set({ selected: false })
target.set({ fill: '#BFFD9F' })
} else {
target.set({ selected: true })
target.set({ fill: 'red' })
}
canvas?.renderAll()
})
}
if (target.name === 'trestle') {
target.on('mousedown', () => {
if (target.defense === 'north') {
alert('북쪽은 선택 불가합니다.')
return
}
if (target.get('selected')) {
target.set({ strokeWidth: 1 })
target.set({ strokeDashArray: [5, 5] })
target.set({ selected: false })
} else {
target.set({ strokeWidth: 5 })
target.set({ strokeDashArray: [0, 0] })
target.set({ selected: true })
}
canvas?.renderAll()
})
}
if (target.name === 'lengthText') {
const x = target.left
const y = target.top
target.on('selected', (e) => {
Object.keys(target.controls).forEach((controlKey) => {
target.setControlVisible(controlKey, false)
})
})
target.on('moving', (e) => {
if (target.parentDirection === 'left' || target.parentDirection === 'right') {
const minX = target.minX
const maxX = target.maxX
if (target.left <= minX) {
target.set({ left: minX, top: y })
} else if (target.left >= maxX) {
target.set({ left: maxX, top: y })
} else {
target.set({ top: y })
}
} else if (target.parentDirection === 'top' || target.parentDirection === 'bottom') {
const minY = target.minY
const maxY = target.maxY
if (target.top <= minY) {
target.set({ left: x, top: minY })
} else if (target.top >= maxY) {
target.set({ left: x, top: maxY })
} else {
target.set({ left: x })
}
}
canvas?.renderAll()
})
}
},
removed: (e) => {
const whiteList = ['mouseLine', 'guideLine']
if (whiteList.includes(e.target.name)) {
return
}
console.log('removed', e)
},
} }
const selectionEvent = { const selectionEvent = {
@ -38,146 +134,15 @@ export function useCanvasEvent() {
}, },
} }
const onChange = (e) => {
const target = e.target
if (target) {
// settleDown(target)
}
}
const removeEventOnCanvas = () => { const removeEventOnCanvas = () => {
canvas?.off('object:added') canvas?.off('object:added')
canvas?.off('object:modified') canvas?.off('object:modified')
canvas?.off('object:removed') canvas?.off('object:removed')
canvas?.off('object:added')
canvas?.off('selection:cleared') canvas?.off('selection:cleared')
canvas?.off('selection:created') canvas?.off('selection:created')
canvas?.off('selection:updated') canvas?.off('selection:updated')
} }
const addEventOnObject = (e) => {
const target = e.target
if (target.type === 'QPolygon' || target.type === 'QLine') {
const textObjs = canvas?.getObjects().filter((obj) => obj.name === 'lengthText')
textObjs.forEach((obj) => {
obj.bringToFront()
})
}
if (target.name === 'cell') {
target.on('mousedown', () => {
if (target.get('selected')) {
target.set({ selected: false })
target.set({ fill: '#BFFD9F' })
} else {
target.set({ selected: true })
target.set({ fill: 'red' })
}
canvas?.renderAll()
})
}
if (target.name === 'trestle') {
target.on('mousedown', () => {
if (target.defense === 'north') {
alert('북쪽은 선택 불가합니다.')
return
}
if (target.get('selected')) {
target.set({ strokeWidth: 1 })
target.set({ strokeDashArray: [5, 5] })
target.set({ selected: false })
} else {
target.set({ strokeWidth: 5 })
target.set({ strokeDashArray: [0, 0] })
target.set({ selected: true })
}
canvas?.renderAll()
})
}
if (target.name === 'lengthText') {
const x = target.left
const y = target.top
target.on('selected', (e) => {
Object.keys(target.controls).forEach((controlKey) => {
target.setControlVisible(controlKey, false)
})
})
target.on('moving', (e) => {
if (target.parentDirection === 'left' || target.parentDirection === 'right') {
const minX = target.minX
const maxX = target.maxX
if (target.left <= minX) {
target.set({ left: minX, top: y })
} else if (target.left >= maxX) {
target.set({ left: maxX, top: y })
} else {
target.set({ top: y })
}
} else if (target.parentDirection === 'top' || target.parentDirection === 'bottom') {
const minY = target.minY
const maxY = target.maxY
if (target.top <= minY) {
target.set({ left: x, top: minY })
} else if (target.top >= maxY) {
target.set({ left: x, top: maxY })
} else {
target.set({ left: x })
}
}
canvas?.renderAll()
})
}
}
// 마우스 가로, 세로선 그리기
const drawMouseLines = (e) => {
// 현재 마우스 포인터의 위치를 가져옵니다.
const pointer = canvas?.getPointer(e.e)
// 기존에 그려진 가이드라인을 제거합니다.
removeMouseLines()
if (canvas?.getActiveObject()) {
return
}
// 가로선을 그립니다.
const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'mouseLine',
})
// 세로선을 그립니다.
const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'mouseLine',
})
// 선들을 캔버스에 추가합니다.
canvas?.add(horizontalLine, verticalLine)
// 캔버스를 다시 그립니다.
canvas?.renderAll()
}
//가로, 세로 선 삭제
const removeMouseLines = () => {
if (canvas?._objects.length > 0) {
const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
mouseLines.forEach((item) => canvas?.remove(item))
}
canvas?.renderAll()
}
/** /**
* 각종 키보드 이벤트 * 각종 키보드 이벤트
* https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values * https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
@ -216,6 +181,16 @@ export function useCanvasEvent() {
case 'Esc': // IE/Edge에서 사용되는 값 case 'Esc': // IE/Edge에서 사용되는 값
case 'Escape': case 'Escape':
break break
case 'z':
if (!e.ctrlKey) {
return
}
console.log('뒤로가기')
break
default: default:
return // 키 이벤트를 처리하지 않는다면 종료합니다. return // 키 이벤트를 처리하지 않는다면 종료합니다.
} }
@ -235,6 +210,7 @@ export function useCanvasEvent() {
} }
targetObj.set({ top: top }) targetObj.set({ top: top })
targetObj.fire('modified')
canvas?.renderAll() canvas?.renderAll()
} }
@ -251,6 +227,7 @@ export function useCanvasEvent() {
} }
targetObj.set({ top: top }) targetObj.set({ top: top })
targetObj.fire('modified')
canvas?.renderAll() canvas?.renderAll()
} }
@ -267,6 +244,7 @@ export function useCanvasEvent() {
} }
targetObj.set({ left: left }) targetObj.set({ left: left })
targetObj.fire('modified')
canvas?.renderAll() canvas?.renderAll()
} }
@ -283,9 +261,29 @@ export function useCanvasEvent() {
} }
targetObj.set({ left: left }) targetObj.set({ left: left })
targetObj.fire('modified')
canvas?.renderAll() canvas?.renderAll()
} }
/**
* 선택한 도형을 삭제한다.
*/
const handleDelete = () => {
const targets = canvas?.getActiveObjects()
if (targets?.length === 0) {
alert('삭제할 대상을 선택해주세요.')
return
}
if (!confirm('정말로 삭제하시겠습니까?')) {
return
}
targets?.forEach((target) => {
canvas?.remove(target)
})
}
return { return {
setCanvasForEvent, setCanvasForEvent,
attachDefaultEventOnCanvas, attachDefaultEventOnCanvas,