本記事では、ドラッグ&ドロップで複数のアイテムの順番を入れ替える実装方法を解説します。
実装例)To Do リストの順番を入れ替える
- Task 1
- Task 2
- Task 3
- Task 4
目次
HTML / CSS / JavaScript コード
<div class="container">
<ul id="todo-list">
<li draggable="true" class="draggable">Task 1</li>
<li draggable="true" class="draggable">Task 2</li>
<li draggable="true" class="draggable">Task 3</li>
<li draggable="true" class="draggable">Task 4</li>
</ul>
</div>
実装のポイント
ドラッグ&ドロップの基礎については以下記事でも解説していますが、改めて本記事でもポイントを解説します。
【JS】ドラッグ&ドロップの実装方法
本記事では、以下のように直感的にアイテムを操作できるドラッグ&ドロップの基本的な実装方法について紹介します。 こちらのブロックをドラッグできます。 ドラッグし…
HTML構造:特定の要素をドラッグできるようにする
draggable="true"
属性を設定することで、設定された要素がドラッグできるようになります。
今回の実装例ではタスク全てを個別にドラッグさせたいので、タスクの構成要素である<li>タグすべてにdraggable="true"
を設定しています。
CSSスタイル:タスクの入れ替えができそうなスタイルを適用する
cursor: move;
を設定することで、カーソルが十字の矢印に変化します。
JavaScriptイベント:ドラッグ&ドロップに関する各種イベントを設定する。
const listItems = document.querySelectorAll('#todo-list li');
listItems.forEach(item => {
// ---略---
});
ドラッグ&ドロップを設定したい全タスクに対し、以下のイベントを設定します。
dragstart
イベント-
ドラッグが開始されたときに発生します。
item.addEventListener('dragstart', (e) => { draggingItem = item; item.classList.add('dragging'); });
ドラッグしているタスクを
draggingItem
に代入し、ドラッグ中のアイテムにはdragging
クラス(CSSプロパティでグレーアウトさせる)を追加します。 dragend
イベント-
ドラッグ操作が終了したときに発生します。
item.addEventListener('dragend', () => { draggingItem.classList.remove('dragging'); draggingItem = null; });
dragstart
イベントとは逆の操作を行います。
ドラッグ中のアイテムからdragging
クラスを削除し、draggingItem
変数の中身をnull
に戻します。 dragover
イベント-
ドラッグ中のタスクが他のタスク上にあるときに発生します。
item.addEventListener('dragover', (e) => { e.preventDefault(); const targetItem = e.target; if (targetItem !== draggingItem) { const bounding = targetItem.getBoundingClientRect(); const offset = bounding.y + bounding.height / 2; const list = document.getElementById('todo-list'); if (e.clientY - offset > 0) { list.insertBefore(draggingItem, targetItem.nextSibling); } else { list.insertBefore(draggingItem, targetItem); } } });
- まず
e.preventDefault();
でデフォルトの動作をキャンセルします。(これを行わないとタスクがドロップできません。) const targetItem = e.target;
でホバーされているタスクの情報を取得し、tagetItem
変数に代入します。if (targetItem !== draggingItem) {…}
:ドラッグ中のタスクが他のタスク上にあるとき(自身のタスクでないとき)にのみ、以下の操作を行います。const bounding = targetItem.getBoundingClientRect();
:ホバーされているタスクの位置とサイズの情報を取得します。const offset = bounding.y + bounding.height / 2;
:ホバーされているタスクの縦方向の中心位置を計算します。if (e.clientY - offset > 0) {...}
:ドラッグ中のタスクの縦方向の位置がホバーされているタスクの中心よりも下にある場合、以下の操作を行います。list.insertBefore(draggingItem, targetItem.nextSibling);
:ドラッグ中のタスクをホバーされているタスクの次(下)に挿入します。
else {...}
:それ以外の場合は、以下の操作を行います。list.insertBefore(draggingItem, targetItem);
:ドラッグ中のタスクをホバーされているタスクの前に挿入します。
- まず
【応用】タスクを追加して保存もできるToDoリスト
タスクを自由に追加でき、さらにブラウザを閉じても内容が保存されるToDoリストを作成しました。
【無料】メモ書きにも使えるToDoリスト
Add Clear 使い方 入力フォームに To Do を入力して「Add」ボタンをクリックすると、To Do が追加される。複数追加も可能。 各To Doはドラッグ&ドロップで順番を入れ替…
実装コードも公開しているので、よろしければ参考にしてみてください。
当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。
Webデザイン・UIコンポーネント集(HTML/CSS/JS)
Webサイトやアプリで使われている『Webデザイン』や『UI』の実装例を纏めました。(随時更新中)実装方法などは別記事にコードや実装ポイントを公開していますので、自…