【特集】

詳解! HTML 5と関連APIの最新動向 - 新タグ&API編

7 ドラッグ&ドロップAPI

    白石俊平  [2009/07/31]

    HTML 5では、ドラッグ&ドロップを直接サポートするためのAPIが整備された。以前はmousedown、mousemove、mouseupを利用してドラッグ&ドロップを実現していたが、ブラウザによるネイティブサポートが実現した事で、他のアプリケーションともデータをやり取りできるようになり、コーディングも簡略化された。

    HTML 5でドラッグ&ドロップを実現するための最小限の手順は以下の通りだ。

    1. ドラッグ対象となる要素に「draggable="true"」という属性値をセットする。これにより、対象の要素がドラッグ可能となる。ちなみに、img要素やa要素(hrefの指定が必要)はデフォルトでドラッグ可能である
    2. ドラッグ&ドロップ関連のイベントを処理するようコードを記述する。以下のようなイベントが存在する
    イベント名イベントの通知先説明
    dragstartドラッグ対象の要素ドラッグが開始された
    dragドラッグ対象の要素ドラッグ中
    dragenterドラッグ中にマウスオーバーした要素ドラッグ操作が要素の範囲内に入った
    dragoverドラッグ中にマウスオーバーした要素ドラッグ操作が要素の範囲内を通過中
    dragleaveドラッグ中にマウスオーバーした要素ドラッグ操作が要素の範囲内を出た
    dropドロップ先の要素ドロップされた
    dragendドラッグ対象の要素ドラッグが終了した

    では、この手順に則ってドラッグ&ドロップを実現したサンプルを以下に示す。以下のサンプルは、「ドラッグしてね!」と表示されているdiv要素を、その下にあるdiv要素に対してドラッグ&ドロップすることができる。ドラッグされるたびに、下のdiv要素には「Hello」という文字列が追加される。

    リスト drag-and-drop1.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>ドラッグ&ドロップのデモ</title>
    <script type="text/javascript">
    function init() {
      var source = document.getElementById("dragme");
      var dest = document.getElementById("text");
      // (1) ドラッグ開始
      source.addEventListener("dragstart", function(ev) {
        // dataTransferオブジェクトに対し、データを追加
        var dt = ev.dataTransfer;
        dt.setData("text/plain", "Hello");
        return true;
      }, false);
      // (2) ドラッグオーバー
      dest.addEventListener("dragover", function(ev) {
        // デフォルトの動作(ドロップの拒否)を行わない
        ev.preventDefault();
        return false;
      }, false);
      // (3) ドロップ
      dest.addEventListener("drop", function(ev) {
        // DataTransferオブジェクトからデータを取得
        var dt = ev.dataTransfer;
        var text = dt.getData("text/plain");
        dest.textContent += text;
        // イベントのバブリングを停止
        ev.stopPropagation();
        return false;
      }, false);
    }
    </script>
    </head>
    <body onload="init()">
    <h1>ドラッグ&ドロップのデモ</h1>
    <!-- (4) draggable属性をtrueに -->
    <div id="dragme" draggable="true" style="-webkit-user-drag: element; width: 200px; border: 1px solid gray;">
      ドラッグしてね!
    </div>
    <div id="text"
      style="width: 200px; height: 200px; border: 1px solid gray;"></div>
    </body>
    </html>
    

    上のソースコードにおけるポイントを解説する。

    (1) ドラッグが開始(dragstartイベント)された際、ドロップするデータをDataTransferオブジェクトにセット(setData()メソッド)する。DataTransferオブジェクトとは、ドラッグイベントのdataTransferプロパティから取得することができ、ドラッグ&ドロップによって持ち運ばれるデータを格納するためのオブジェクトだ。同オブジェクトのsetData()メソッドは、第1引数にデータの種別を表す文字列、第2引数にデータ自体を指定する。第1引数のデータ種別には任意の文字列を指定できるだけではなく、「text/plain」や「text/html」といったMIMEタイプも指定することができる。

    (2) ドロップを受け付ける要素に対しては、dragoverイベント内で「イベントオブジェクト.preventDefault()」を呼び出す必要がある。これは、dragoverイベントのデフォルト動作が「ドロップ拒否」になっているため。このデフォルト動作を停止しないと、ドロップを受け付けることができない。

    (3) ドロップされたら、DataTransferオブジェクトからデータを取得(getData()メソッド)して処理を行う。getData()の引数には、setData()時に指定したデータ種別(ここでは「text/plain」)を指定する。

    (4) ドラッグ可能な要素には「draggable="true"」を指定する必要がある。またこのサンプルでは、現在のSafariやChromeでも動作するように、"-webkit-user-drag: element;"というWebkit固有のCSSプロパティを指定している。

    さらにこのサンプルは、データ種別として「text/plain」というMIMEタイプを使用しているため、同MIMEタイプを解釈できる他のアプリケーションともデータのやり取りが可能だ。

    他のアプリともデータのやり取りが可能(画像はSafariから文字列をドラッグしている)

    ドラッグ&ドロップ処理で使用される一般的なMIMEタイプとしては以下のようなものが挙げられる。

    • text/plain … テキストデータ
    • text/html … HTML文字列
    • text/xml … XML文字列
    • text/uri-list … URLのリスト。各URLは改行で区切られる

    残念ながら、OSネイティブのファイルをドラッグ&ドロップで取得するための汎用的な方法は存在しない。

    ドラッグ&ドロップに関するその他のAPI

    ドラッグ&ドロップに関するその他のAPIを駆使すれば、ドラッグ中のイメージをカスタマイズしたり、特定の操作(コピー/移動/リンクなど)以外はドロップを受け付けないようにするなど、さらに高度な処理を実現可能だ。そうした処理を実現するため、DataTransferオブジェクトに用意されているAPIを簡単に挙げておく

    属性/メソッド説明
    DOMString dropEffectドロップ操作の種別を表す。明示的に値をセットする事も可能。ドロップ先がこの種別のドロップを許可していなかったら、ドロップが受け付けられない。指定できる値(文字列)はnone、copy、link、 moveのいずれか。
    DOMString effectAllowedドロップを受け付ける操作の種別を表す。指定できる値(文字列)はnone、copy、copyLink、copyMove、link、linkMove、move、all、uninitializeのいずれか。
    DOMStringType types格納されているデータの種別を、文字列の擬似配列として返す
    void clearData(DOMString format)データをクリアする。引数formatを省略すると、すべてのデータがクリアされる
    void setData(DOMString format, DOMString data)データをセットする
    DOMString getData(DOMString format)データを取得する
    void setDragImage(Element image, long x, long y)ドラッグ中のイメージをimg要素でセットする(ブラウザによってはcanvasなども受け付けられる)
    void addElement(Element element)ドラッグ対象の要素を追加する

    まとめ

    今回は「HTML 5 - HTMLとXHTML向けのボキャブラリと関連API」から、HTML 5で新しく導入されたタグやAPIを中心にお伝えした。次回はアプリケーションキャッシュやWeb Storageなど、次世代のWebアプリケーションを実現するための各種APIを解説したいと思う。

    関連記事

    関連サイト

    関連したタグ

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン