ホーム > Web技術 > HTML5のドラッグ&ドロップ実装方法

HTML5のドラッグ&ドロップ実装方法

2012 年 1 月 31 日 コメントをどうぞ コメント

HTML5対応のブラウザで利用できるドラッグ&ドロップの使い方を調べてみました。

ドラッグ&ドロップの実装は、ドラッグ側とドロップ側に分けて考える必要があります。HTML内の要素をドラッグして同じHTML内にドロップするのであれば両方必要ですし、OSのファイルをドラッグしてHTMLにドロップするのであればドロップ側の実装だけで済みます。

それでは、HTML5でのドラッグ&ドロップ実装がどうなるのか見てみましょう。

ドラッグする要素

ドラッグする要素には、draggable=”true” という属性を指定します。

<ul id="drag">
<li draggable="true">Draggable element 1</li>
<li draggable="true">Draggable element 2</li>
<li draggable="true">Draggable element 3</li>
</ul>

これだけではドラッグが出来ません。次にドラッグイベントのハンドラを登録します。

var drag = document.getElementById("drag");
drag.addEventListener('dragstart', onDragStart, false);
drag.addEventListener('dragend', onDragEnd, false);

ドラッグ開始イベント(dragstart)では、ドラッグするデータを登録します。イベントのdataTransferオブジェクトにMIMEをキーとする文字列データを登録します。これで要素がドラッグできるようになります。
ちなみに、MIMEを変えれば複数の登録ができます。どのデータを使うかはドロップ側の処理次第です。

function onDragStart(event) {
    event.dataTransfer.setData('text/plain', event.target.textContent);
    event.dataTransfer.setData('text/html', event.target.innerHTML);
}

ドラッグ終了イベント(dragend)では、ドラッグ側の後処理を行います。dataTransferオブジェクトのdropEffectプロパティを見れば、ドロップされた(copy, move, link)のか、ドロップされなかった(none)のかを判断できます。以下はドラッグ&ドロップした後に元の要素を削除する例です。

function onDragEnd(event) {
    if (event.dataTransfer.dropEffect == "move")
        event.target.parentNode.removeChild(event.target);
}

ドロップする要素

続いて、ドラッグを受け入れるドロップ要素の指定です。仕様では dropzone=ドロップ条件 の属性を指定すればよいのですが、現時点ではブラウザが対応していないようです。

<div id="drop" dropzone="copy s:text/plain">Drop here</div>
<!-- これはtext/plainデータを受け入れる指定だが現時点では使えない -->

仕方がないのでdropzoneは使いません。ドラッグイベントのハンドラを登録して、ドラッグを受け入れることを宣言します。

var drop = document.getElementById("drop");
drop.addEventListener("dragenter", onDropCheck, false);
drop.addEventListener("dragover", onDropCheck, false);
drop.addEventListener("drop", onDrop, false);

ドラッグ中は真下の要素に対して dragenter, dragover, dragleave のイベントが発生します。このイベントのデフォルト動作は”ドラッグを受け入れない”なので、デフォルト動作をキャンセル(preventDefault)することがドラッグを受け入れる意思表示となります。

function onDropCheck(event) {
    if (event.dataTransfer.types.indexOf("text/plain") != -1)
        event.preventDefault();
}

ドロップイベント(drop)では、ドロップされた側の処理を行います。イベントのdataTransferオブジェクトから、MIMEに対応するデータを取得して何かを行えばよいのです。

function onDrop(event) {
    event.target.textContent = event.dataTransfer.getData("text/plain");
    event.preventDefault();
}

イベントの流れ

ドラッグイベントの流れを表にしたものを載せておきます。

マウスの操作 発生するイベント イベントの対象
ボタンを押す dragstart ドラッグ要素
マウスを動かす drag ドラッグ要素
dragenter ドロップ要素
dragover ドロップ要素
dragleave ドロップ要素
ボタンを離す drop ドロップ要素
dragend ドラッグ要素

最後に

ドラッグ&ドロップの基本的な説明は以上です。想像していたよりも簡単でした。とはいえ、無理にこの仕組みを使う必要もないのかなとも感じています。

Webアプリ内で特定要素をドラッグできるようにする場合、わざわざHTML5の仕組みを使うメリットは無く、jQueryなどのライブラリを使った方が簡単に実現できます。

逆に外部とやり取りする場合、例えば、OSのファイルをHTMLにドロップできる機能を持たせたり、別のウィンドウ間でドラッグ&ドロップするような使い方では、HTML5のこの仕組みが合っています。
(ファイルをHTMLにドロップする使い方は次回のエントリーに書く予定です)

ドラッグ&ドロップについてもっと詳しい内容を知りたい方は、本家W3Cのドラフト仕様をご覧ください。

カテゴリー: Web技術
  1. コメントはまだありません。
  1. トラックバックはまだありません。

スパム投稿ではないことを確認するため、計算式の答えを半角数字で入力してください。 * Time limit is exhausted. Please reload the CAPTCHA.