diff --git a/resources/views/rd/planning-design/index.blade.php b/resources/views/rd/planning-design/index.blade.php index 26584332..e131dace 100644 --- a/resources/views/rd/planning-design/index.blade.php +++ b/resources/views/rd/planning-design/index.blade.php @@ -504,7 +504,7 @@ } -
+
{{-- ===== Top Toolbar ===== --}}
@@ -1054,7 +1054,8 @@
빠른 노드 추가
-
삭제
+
연결선 삭제
+
노드 삭제
@@ -1117,6 +1118,7 @@ function planningCanvas() { panning: false, panStartX: 0, panStartY: 0, + spaceHeld: false, // Connection Drawing drawingConnection: false, @@ -1509,11 +1511,22 @@ function planningCanvas() { // ===== Canvas Events ===== onCanvasMouseDown(e) { - if (e.target.closest('.pc-node') || e.target.closest('.pc-port')) return; - if (this.tool === 'pan' || e.button === 1) { + if (e.target.closest('.pc-node') || e.target.closest('.pc-port')) { + // 스페이스바 누른 채 노드 위에서도 패닝 가능 + if (this.spaceHeld) { + this.panning = true; + this.panStartX = e.clientX - this.panX * this.zoom; + this.panStartY = e.clientY - this.panY * this.zoom; + document.getElementById('canvasWrap')?.style.setProperty('cursor', 'grabbing'); + e.preventDefault(); + } + return; + } + if (this.tool === 'pan' || this.spaceHeld || e.button === 1) { this.panning = true; this.panStartX = e.clientX - this.panX * this.zoom; this.panStartY = e.clientY - this.panY * this.zoom; + document.getElementById('canvasWrap')?.style.setProperty('cursor', 'grabbing'); e.preventDefault(); } else { this.selectedNode = null; @@ -1551,7 +1564,12 @@ function planningCanvas() { this.pushHistory(); this.autoSave(); } - if (this.panning) { this.panning = false; } + if (this.panning) { + this.panning = false; + const wrap = document.getElementById('canvasWrap'); + if (this.spaceHeld) wrap?.style.setProperty('cursor', 'grab'); + else wrap?.style.removeProperty('cursor'); + } if (this.drawingConnection) { // Check if dropped on a node port const target = e.target.closest('.pc-node'); @@ -1699,11 +1717,22 @@ function planningCanvas() { // ===== Keyboard Shortcuts ===== handleKeyDown(e) { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) return; + + // 스페이스바: 패닝 모드 (누르고 있는 동안) + if (e.key === ' ' || e.code === 'Space') { + e.preventDefault(); + if (!this.spaceHeld) { + this.spaceHeld = true; + this._toolBeforeSpace = this.tool; + this.tool = 'pan'; + document.getElementById('canvasWrap')?.style.setProperty('cursor', 'grab'); + } + return; + } + if (e.key === 'Delete' || e.key === 'Backspace') { if (this.selectedConnection) { - this.connections = this.connections.filter(c => c.id !== this.selectedConnection.id); - this.selectedConnection = null; - this.pushHistory(); this.autoSave(); + this.deleteSelectedConnection(); } else { this.deleteSelectedNode(); } @@ -1726,6 +1755,26 @@ function planningCanvas() { } }, + handleKeyUp(e) { + if (e.key === ' ' || e.code === 'Space') { + if (this.spaceHeld) { + this.spaceHeld = false; + this.panning = false; + this.tool = this._toolBeforeSpace || 'select'; + document.getElementById('canvasWrap')?.style.removeProperty('cursor'); + } + } + }, + + // ===== Connection Delete ===== + deleteSelectedConnection() { + if (!this.selectedConnection) return; + this.connections = this.connections.filter(c => c.id !== this.selectedConnection.id); + this.selectedConnection = null; + this.pushHistory(); + this.autoSave(); + }, + // ===== Context Menu ===== showContextMenu(e) { this.contextMenuPos = { x: e.clientX, y: e.clientY };