ドラッグ&ドロップとは、ウェブページ内の要素やローカル環境に保存されたファイルなどのデータを、 マウスで引きずるように移動させて他の場所に置く操作のことです。 HTML5以前にも、mousedownやmouseupなどのイベントで実現することはできましたが、 HTML5ではドラッグ&ドロップ専用の新しいイベントや新しいメソッド・属性が追加されています。
ドラッグ&ドロップを理解するには、ドラッグ操作とドロップ操作を分けて考えると理解しやすいでしょう。 ドラッグ操作は要素などのデータをマウスでつかんで引きずるように動かすこと、 ドロップ操作はその動かしたデータをドロップ先の要素内に配置することです。
HTML側では、ドラッグする要素にdraggable属性を指定します。 draggable属性の値には、true・false・値なしのいずれかを指定します。 値を指定しない場合にはデフォルト動作となります。
href属性が指定されたa要素、および、src属性が指定されたimg要素は、デフォルトでドラッグ可となっています。 それ以外の要素は、デフォルトではドラッグ不可です。
HTML source
<div id="apple" draggable="true">りんご</div>
ドロップ先の要素にはdropzone属性を指定することになっています。
ただし、現在のところdropzone属性をサポートしているブラウザはまだ無い(?)ようなので、 また、dropzone属性を使用しなくても一部ブラウザでドラッグ&ドロップ機能を実現できるので、 このページで紹介するサンプルではひとまずdropzone属性を指定していません。
JavaScript側では、ドラッグ開始時にDataTransferというオブジェクトにドラッグするデータをセットしておき、 ドロップ時にそのデータを取り出して、ドラッグデータをドロップ先へ受け渡すことでドラッグ&ドロップを実現します。
この際、データのセットに使用するのがsetData()メソッド、 データの取得に使用するのがgetData()メソッドです。
// データをセットする
dataTransfer . setData(format, data);
// データを取得する
data = dataTransfer . getData(format);
ユーザーによるドラッグ操作やドロップ操作は、以下の7つのイベントで取得します。 それぞれのイベント発生時におけるドラッグデータ、および、 ドロップ先の要素の挙動をJavaScriptで制御してやることで、ドラッグ&ドロップ機能を実現します。
イベント名 | イベントが発生するタイミング | デフォルト動作 |
---|---|---|
dragstart | ドラッグ開始時 | ドラッグを開始する |
drag | ドラッグが継続している間 | ドラッグを継続する |
dragenter | ドラッグ要素がドロップ要素に入った時 | ユーザーによるドロップ操作を拒否 |
dragleave | ドラッグ要素がドロップ要素から出た時 | 何もしない |
dragover | ドラッグ要素がドロップ要素に重なっている間 | 現在のドラッグ操作をリセットする |
drop | ドロップ時 | (場合による) |
dragend | ドラッグ終了時 | (場合による) |
ドラッグ操作では、ドラッグするデータをDataTransferオブジェクトにセットすることで、ドロップ先に受け渡すことのできる状態にします。
JavaScript source
ソース
// ドラッグ開始時の処理
function f_dragstart(event){
//ドラッグするデータのid名をDataTransferオブジェクトにセット
event.dataTransfer.setData("text", event.target.id);
};
色付きのボックスを左のボックスから右のボックスに移動できます。
HTML source
<div id="box1">
<div id="item" draggable="true" ondragstart="drag(event)"></div>
</div>
<div id="box2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
CSS source
#box1, #box2 {
float: left;
width: 70px;
height: 70px;
border: 1px solid #999;
}
#item {
margin: 3px;
width: 50px;
height: 50px;
background-color: #900;
border: 1px solid #999;
}
JavaScript source
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
let data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}