HTML ドラッグアンドドロップ API の使い方

ドラッグアンドドロップは、ユーザーの操作性を高め、シームレスなユーザーエクスペリエンスを実現する上で欠かせない機能です。ファイルアップローダー、並べ替え可能なリスト、インタラクティブなゲームを作成する場合でも、この API の機能を理解することは Web 開発ツールキットに欠かせないスキルです。

HTML のドラッグアンドドロップの基本

一般的なドラッグアンドドロップシステムでは、2 種類の要素があります。1 つ目は、ユーザーがマウスで移動できるドラッグ可能な要素で、2 つ目は、ユーザーが要素を配置できる場所を指定するドロップ可能な要素です。

ドラッグアンドドロップを実装するには、ブラウザにどの要素をドラッグ可能にするかを伝える必要があります。ユーザーが要素をドラッグできるようにするには、その要素にdraggableHTML 属性をtrueに設定します。次のようになります。

<div draggable="true">この要素はドラッグ可能です</div>

ユーザーがドラッグイベントを開始すると、ブラウザは通常、ドラッグされている要素に関するフィードバックを提供するデフォルトの「ゴースト」画像を提供します。

代わりに独自の画像を提供することで、この画像をカスタマイズできます。これを行うには、DOM からドラッグ可能な要素を選択し、カスタムフィードバック画像を表す新しい画像を作成し、dragstartドラッグイベントリスナーを次のように追加します。

let img = new Image();
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Twemoji_1f600.svg/220px-Twemoji_1f600.svg.png';
document.querySelector('div').addEventListener('dragstart', (event)=>{
event.dataTransfer.setDragImage(img, 10, 10);
})

上記のコードブロックで、setDragImageメソッドには 3 つの引数があります。1 番目の引数は画像を参照します。他の引数は、それぞれ画像の水平方向と垂直方向のオフセットを表します。ブラウザでコードを実行し、要素のドラッグを開始すると、カスタムドラッグ画像が以前に設定されたカスタム画像に置き換えられたことがわかります。

ドロップを許可する場合は、dragenterdragoverの両方のイベントをキャンセルしてデフォルトの動作を防止する必要があります。次のようになります。

const dropElement = document.querySelector("drop-target");
dropElement.addEventListener("dragenter", (ev) => {
ev.preventDefault();
});
dropElement.addEventListener("dragover", (ev) => {
ev.preventDefault();
});

DragEvent インターフェースを理解する

JavaScript には、ユーザーのドラッグアンドドロップ操作を表すDragEventインターフェースがあります。以下は、DragEventインターフェースで可能なイベントタイプのリストです。

  • drag: ユーザーが要素をドラッグしている間にこのイベントが発生します。
  • dragend: ドラッグ操作が終了したとき、またはユーザーが中断したときにこのイベントが発生します。一般的なドラッグ操作は、マウスボタンを離すか、エスケープキーを押すことで終了します。
  • dragenter: ドラッグされた要素が有効なドロップターゲットに入ったときにこのイベントが発生します。
  • dragleave: ドラッグされた要素がドロップターゲットから外れたときにこのイベントが発生します。
  • dragover: ユーザーがドラッグ可能な要素をドロップターゲット上にドラッグすると、このイベントが発生します。
  • dragstart: ドラッグ操作の開始時にこのイベントが発生します。
  • drop: ユーザーが要素をドロップターゲットにドロップしたときにこのイベントが発生します。

ブラウザの外部の環境 (たとえば、オペレーティングシステムのファイルマネージャー) からブラウザにファイルをドラッグすると、ブラウザはdragstartまたはdragendイベントをトリガーしません。

プログラムでカスタムドラッグイベントをディスパッチする場合、DragEventが役立ちます。たとえば、ページの読み込み時にdivでカスタムドラッグイベントを発生させる場合、次のようにします。まず、次のように新しいカスタムDragEvent()を作成します。

const customDragStartEvent = new DragEvent('dragstart', {
dataTransfer: new DataTransfer(),
})
const customDragEndEvent = new DragEvent('dragend');

上記のコードブロックで、customDragStartEventDragEvent()のインスタンスを表します。customDragStartEventには、2 つのコンストラクター引数があります。1 つ目はドラッグイベントの種類を表し、前に述べた 7 つのイベントタイプのいずれかになります。

2 番目の引数は、DataTransferのインスタンスを表すdataTransferキーを持つオブジェクトです。これについては、このガイドの後半で詳しく説明します。次に、Document Object Model (DOM) からイベントをトリガーする要素を取得します。

const draggableElement = document.querySelector("#draggable");

次に、次のようにイベントリスナーを追加します。

draggableElement.addEventListener('dragstart', (event) => {
console.log('ドラッグが開始されました!');
event.dataTransfer.setData('text/plain', 'こんにちは、世界!');
});
draggableElement.addEventListener('dragend', () => {
console.log('ドラッグが終了しました!');
});

上記の最初のイベントリスナーで、コールバック関数は「ドラッグが開始されました!」というテキストを記録し、eventオブジェクトのdataTransferプロパティでsetDataメソッドを呼び出します。これで、次のようにカスタムイベントをトリガーできます。

draggableElement.dispatchEvent(customDragStartEvent);
draggableElement.dispatchEvent(customDragEndEvent);

dataTransfer でデータを転送する

dataTransferオブジェクトは、ドラッグアンドドロップ操作中にソース要素(ドラッグ可能なアイテム)とターゲット要素(ドロップ可能な領域)間の橋渡しとして機能します。これらは、これらの要素間で共有するデータの一時的な格納コンテナーとして機能します。

このデータは、テキスト、URL、またはカスタムデータ型など、さまざまな形式をとることができるため、幅広いドラッグアンドドロップ機能を実装するための汎用的なツールになります。

setData() を使用してデータをパッケージ化

ドラッグ可能な要素からドロップ可能な要素にデータを転送するには、dataTransferオブジェクトによって提供されるsetData()メソッドを使用します。このメソッドを使用すると、転送するデータをパッケージ化し、データの種類を指定できます。基本的な例を次に示します。

element.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'こんにちは、世界!');
});

ユーザーが指定された要素のドラッグを開始すると、setData()はテキスト「こんにちは、世界!」をデータ型text/plainでパッケージ化します。このデータはドラッグイベントに関連付けられ、ドロップ操作中にドロップ可能なターゲットからアクセスできます。

getData() を使用してデータを取得する

受信側では、ドロップ可能な要素のイベントリスナー内で、getData()メソッドを使用して転送されたデータを取得できます。

element.addEventListener('drop', (event) => {const transferredData = event.dataTransfer.getData('text/plain');console.log(受信したデータ: ${transferredData});});

上記のコードブロックは、setData()メソッドを使用して以前に設定されたものと同じデータ型(text/plain)でデータを取得します。これにより、ドロップ可能な要素のコンテキスト内で必要に応じて転送されたデータにアクセスして操作できます。

ドラッグアンドドロップインターフェースのユースケース

ドラッグアンドドロップ機能を Web アプリケーションに統合することは強力な強化になりますが、いつ、なぜ実装すべきかを理解することが重要です。

  • ファイルアップローダー: ユーザーがデスクトップやファイルマネージャーからファイルを直接指定されたドロップ領域にドラッグできるようにすることで、アップロードプロセスが簡素化されます。
  • 並べ替え可能なリスト: アプリケーションにタスクリスト、プレイリスト、画像ギャラリーなどのアイテムのリストが含まれている場合、ユーザーはドラッグアンドドロップでアイテムを並べ替えることができることを高く評価する可能性があります。
  • インタラクティブダッシュボード: データの視覚化とレポートツールの場合、ドラッグアンドドロップはユーザーがウィジェットやグラフを並べ替えてダッシュボードをカスタマイズする強力な方法です。

アクセシビリティを念頭に置く

ドラッグアンドドロップは視覚的に魅力的で、ユーザーエクスペリエンスを向上させることができますが、実装が障害のあるユーザーを含むすべてのユーザーがアクセスできるようにすることが重要です。キーボードコントロールなどの代替的な操作方法を提供して、アプリケーションを包括的なものにします。