タイトル: Drag and Drop API
SEOタイトル: HTML5 Drag and Drop API 完全ガイド(dragstart/drop/dataTransfer の使い方)
| この記事の要点 |
|
Drag and Drop API とは
HTML5 Drag and Drop API(DnD API)は、ブラウザがネイティブでサポートするドラッグ&ドロップ機構です。要素を別の場所にマウス/タッチで運んだり、デスクトップからファイルをブラウザに投げ込んだりできます。jQuery UI や独自実装に頼らずに、純粋な DOM イベントだけで実現できるのが利点です。
基本フロー
| 段階 | 発火イベント | 対象 | 主な処理 |
|---|---|---|---|
| 掴む | dragstart | ドラッグ元 | dataTransfer.setData() でデータをセット |
| 運ぶ | drag | ドラッグ元 | 連続発火。UI 演出に使う |
| 上を通過 | dragenter / dragover | ドロップ先 | preventDefault() 必須 |
| 離脱 | dragleave | ドロップ先 | ホバー演出を解除 |
| 離す | drop | ドロップ先 | dataTransfer.getData() で受け取り |
| 終了 | dragend | ドラッグ元 | クリーンアップ |
最小実装例
Drag me
Drop here
dataTransfer オブジェクト
ドラッグ元とドロップ先の間でデータを受け渡すのが event.dataTransfer です。
| プロパティ / メソッド | 用途 |
|---|---|
setData(type, value) | データを格納。type は MIME(text/plain, text/html, application/json 等) |
getData(type) | データ取得。drop ハンドラ内でのみ |
files | OS から D&D されたファイル(FileList) |
effectAllowed | 許可される動作 copy / move / link / all |
dropEffect | カーソル表示(copy/move/link/none) |
setDragImage(el, x, y) | ドラッグ中のサムネ画像を差し替え |
ファイルの D&D(最頻出ユースケース)
Drop files here
preventDefault を忘れる罠
仕様上、ブラウザはデフォルトでは「ドロップを禁止する」動作になっています。dragover で preventDefault() を呼ばないと drop イベントが発火しません。これが Drag and Drop API で最も多いハマりどころです。
// ❌ NG: drop が発火しない
dst.addEventListener('drop', handler);
// ✅ OK
dst.addEventListener('dragover', (e) => e.preventDefault());
dst.addEventListener('drop', handler);
並べ替え(ソート)UI の実装
- Apple
- Banana
- Cherry
フォールバック / 制約
- モバイル(iOS Safari など)はネイティブ DnD 非対応に近い。Pointer Events や touch イベントで自前実装が必要
- キーボード操作・スクリーンリーダー対応が弱い → アクセシビリティ重視なら
dnd-kitを採用 dataTransfer.setData('text/uri-list', url)で URL D&D に対応- セキュリティ上、別オリジン間でのファイルパス取得は禁止
モダンライブラリの選び方
| ライブラリ | 用途 | 特徴 |
|---|---|---|
| SortableJS | リスト並べ替え | Vanilla JS、フレームワーク非依存、軽量 |
| dnd-kit | React | アクセシビリティ良好、Tree / Kanban 対応、ヘッドレス |
| react-dnd | React | 古参、HTML5 backend と touch backend を切替 |
| vue.draggable.next | Vue 3 | SortableJS のラッパー |
| Interact.js | 汎用 | リサイズ・ジェスチャ込み、低レイヤ |
FAQ
Q: drop イベントが発火しません
A: 99% は dragover の preventDefault() 忘れです。dragenter でも入れておくと確実。
Q: スマホでドラッグできません
A: HTML5 DnD はモバイルでは動作が不安定です。SortableJS(touch サポートあり)や Pointer Events を用いた自前実装に切り替えてください。
Q: ドラッグ中の見た目を変えたい
A: dragstart で e.dataTransfer.setDragImage(canvasEl, 0, 0)。canvas に好きな画像を描いて差し替えます。