diff --git a/kenban_test/kenban_test.js b/kenban_test/kenban_test.js index 73e1721..356b066 100644 --- a/kenban_test/kenban_test.js +++ b/kenban_test/kenban_test.js @@ -31,6 +31,7 @@ let dragStart_16th = 0; let dragStartNote = null; let selectionRect = { startX: 0, startY: 0, currentX: 0, currentY: 0 }; // 範囲選択の矩形座標 +let dragStartEvent = null; // ================================================================== // ========== 初期化処理 ========== @@ -286,12 +287,17 @@ window.addEventListener('keydown', handleKeyDown); } -function getMousePos(event) { +function getMousePos(event, useInitialEvent = false) { + const sourceEvent = useInitialEvent ? dragStartEvent : event; const rect = canvas.getBoundingClientRect(); - return { x: event.clientX - rect.left, y: event.clientY - rect.top }; + return { + x: sourceEvent.clientX - rect.left, + y: sourceEvent.clientY - rect.top + }; } function handleMouseDown(event) { + dragStartEvent = event; const pos = getMousePos(event); if (pos.x < pitchHeaderWidth) return; @@ -338,25 +344,60 @@ } } +/** + * マウスが動いたときの処理(グループの縦横移動に対応) + */ function handleMouseMove(event) { if (!isDragging && !isSelecting) return; + const pos = getMousePos(event); - const current_16th_col = Math.max(0, Math.floor((pos.x - pitchHeaderWidth) / (cellWidth / 2))); - const diff_16th = current_16th_col - dragStart_16th; + // 現在のマウスカーソル位置(16分音符単位と音階単位)を計算 + const current_16th_col = Math.max(0, Math.floor((pos.x - pitchHeaderWidth) / (cellWidth / 2))); + const currentRow = Math.floor(pos.y / cellHeight); + if (dragMode === 'move-group') { - // グループ移動 + // --- グループ移動 --- + const diff_16th = current_16th_col - dragStart_16th; + + // ▼▼▼ 縦方向の移動量計算を追加 ▼▼▼ + const startRow = Math.floor(getMousePos(event, true).y / cellHeight); // ドラッグ開始時の行 + const dragStartNoteRow = noteScales.indexOf(dragStartNote.scale); + const diff_row = currentRow - dragStartNoteRow; + // ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ + selectedNotes.forEach(note => { + // 横方向の移動 note.start_16th = Math.max(0, note.originalState.start_16th + diff_16th); + + // ▼▼▼ 縦方向の移動 ▼▼▼ + const originalRow = noteScales.indexOf(note.originalState.scale); + const newRow = originalRow + diff_row; + + // ピアノロールの範囲外に移動しないように制限 + if (newRow >= 0 && newRow < noteScales.length) { + note.scale = noteScales[newRow]; + } + // ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ }); - } - else if (dragMode === 'move' && selectedNote) { - selectedNote.start_16th = Math.max(0, dragStartNote.start_16th + diff_16th); } + else if (dragMode === 'move' && selectedNote) { + // --- 単一ノートの移動 --- + const diff_16th = current_16th_col - dragStart_16th; + selectedNote.start_16th = Math.max(0, dragStartNote.start_16th + diff_16th); + + // ▼▼▼ 単一ノートの縦移動も追加 ▼▼▼ + if (currentRow >= 0 && currentRow < noteScales.length) { + selectedNote.scale = noteScales[currentRow]; + } + // ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ + } else if (dragMode === 'resize-right' && selectedNote) { + const diff_16th = current_16th_col - dragStart_16th; selectedNote.length_16th = Math.max(1, dragStartNote.length_16th + diff_16th); } else if (dragMode === 'resize-left' && selectedNote) { + const diff_16th = current_16th_col - dragStart_16th; const newStart = dragStartNote.start_16th + diff_16th; if (newStart < dragStartNote.start_16th + dragStartNote.length_16th) { const finalNewStart = Math.max(0, newStart); @@ -368,6 +409,7 @@ } } else if (isSelecting) { + // --- 範囲選択 --- selectionRect.currentX = pos.x; selectionRect.currentY = pos.y; updateSelection();