ドラッグ&ドロップ(Drag and Drop)は、ユーザーが直感的に要素を移動できるインタラクションを実現するために使用されます。dragstart
、dragover
、drop
などのイベントを組み合わせることで、アイテムの移動やファイルアップロードといった多様な操作をサポートできます。
ドラッグ&ドロップは以下のような流れで処理されます。
- ドラッグ操作が開始されたときに発生します。
- データ転送の設定(例: テキストや画像)や、ドラッグされる要素のスタイル変更を行います。
- 要素がドラッグ可能な対象(ドロップゾーン)の上にある間、継続的に発生します。
- デフォルトの動作を防ぐ(
event.preventDefault()
)ことで、要素がそのゾーンにドロップ可能かを指定します。
- 要素がドロップゾーンにドロップされたときに発生します。
- ドロップされたデータの取得や処理を行います。
以下は、四角形を別のエリアにドラッグ&ドロップするシンプルな実装例です。
See the Pen dragstart / dragover / drop by tones (@tonescodedesign) on CodePen.
JavaScript
const draggable = document.getElementById('draggable');
const dropzone = document.getElementById('dropzone');
// ドラッグ開始時
draggable.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'This is a draggable element.');
draggable.style.opacity = '0.5';
console.log('ドラッグ開始');
});
// ドラッグ終了時
draggable.addEventListener('dragend', () => {
draggable.style.opacity = '1';
console.log('ドラッグ終了');
});
// ドロップゾーンの上にいる間
dropzone.addEventListener('dragover', (event) => {
event.preventDefault(); // デフォルト動作を防ぐ(ドロップを許可)
dropzone.classList.add('over');
console.log('ドラッグオーバー中');
});
// ドロップゾーンを離れたとき
dropzone.addEventListener('dragleave', () => {
dropzone.classList.remove('over');
console.log('ドラッグエリア外に出た');
});
// ドロップ時
dropzone.addEventListener('drop', (event) => {
event.preventDefault();
const data = event.dataTransfer.getData('text/plain');
dropzone.textContent = `ドロップされました: ${data}`;
dropzone.classList.remove('over');
console.log('ドロップ成功');
});
HTML
<div id="draggable" class="draggable" draggable="true">ドラッグ</div>
<div id="dropzone" class="dropzone">ここにドロップ</div>
CSS
.draggable {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
background-color: skyblue;
margin: 20px;
cursor: grab;
}
.dropzone {
width: 300px;
height: 200px;
border: 2px dashed gray;
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
.dropzone.over {
border-color: green;
}
- ドラッグ操作の開始を検知します。
event.dataTransfer
を使用して、ドラッグ中に転送するデータを設定可能です。
JavaScript
element.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text', 'ドラッグデータ');
console.log('ドラッグが開始されました');
});
- 要素がドロップゾーンの上にある間に継続して発生します。
event.preventDefault()
を必ず呼び出す必要があります(呼び出さないとドロップが無効化される)。
JavaScript
dropzone.addEventListener('dragover', (event) => {
event.preventDefault();
});
- ドラッグされた要素がドロップゾーン内にドロップされたときに発生します。
- ドロップデータを取得して処理を実行します。
JavaScript
dropzone.addEventListener('drop', (event) => {
event.preventDefault();
const data = event.dataTransfer.getData('text');
console.log('ドロップされたデータ:', data);
});
以下は、ファイルをドラッグ&ドロップでアップロードする実装例です。
See the Pen dragstart / dragover / drop by tones (@tonescodedesign) on CodePen.
JavaScript
const dropzone = document.getElementById('dropzone');
dropzone.addEventListener('dragover', (event) => {
event.preventDefault();
dropzone.classList.add('over');
});
dropzone.addEventListener('dragleave', () => {
dropzone.classList.remove('over');
});
dropzone.addEventListener('drop', (event) => {
event.preventDefault();
dropzone.classList.remove('over');
const files = event.dataTransfer.files;
console.log('ドロップされたファイル:', files);
if (files.length > 0) {
Array.from(files).forEach(file => {
console.log(`ファイル名: ${file.name}, サイズ: ${file.size}バイト`);
});
}
});
HTML
<div id="dropzone" class="dropzone">ここにファイルをドロップしてください</div>
CSS
.dropzone {
width: 300px;
height: 200px;
border: 2px dashed gray;
display: flex;
justify-content: center;
align-items: center;
margin: 20px auto;
text-align: center;
}
.dropzone.over {
border-color: green;
background-color: #f0fff0;
}
dragover
やdrop
イベントでデフォルト動作を防ぐことが必須です。これを行わないと、ブラウザがデフォルトのドラッグ&ドロップ動作を処理します(例: ファイルを開くなど)。
ドラッグ可能な要素にはdraggable="true"
を明示的に設定します。
ドラッグ中にデータを転送するためのメカニズムを提供します。setData
でデータを設定し、getData
で取得します。
- キーボード操作でも同等の機能を提供するように配慮してください。
- スクリーンリーダーで適切に動作するように、
aria-describedby
やaria-grabbed
属性を利用します。 - 視覚的な変化だけではなく、音声やテキストでも状態の変化を通知しましょう。
HTML
<div id="dropzone" role="button" aria-label="ドラッグアンドドロップのドロップエリア">
ここにドラッグしてドロップしてください。
</div>