JavaScriptを使って要素をドラッグ&ドロップで移動

ドラッグ&ドロップで色々なものを移動させる UI が最近は多くなってきました。モバイルなどでも直感的でわかりやすいため色々な場面で利用されているように感じます。

この記事では要素をマウスによるドラッグ&ドロップまたはスマホでのタッチイベントで動かせるように JavaScript コードを書いています。よく使われている技術なので有名なコードかもしれませんが、自分なりに考えてみました。ネイティブな JavaScript コードです。PC とモバイル一応対応済み。

drag-and-drop

使い方

.drag-and-drop のクラス名が付いた要素をドラッグ&ドロップで移動できるようにします。複数あっても大丈夫なように書いたので .drag-and-drop はいくつあっても大丈夫です。

HTML例

<div class="drag-and-drop" id="red-box"></div>
<div class="drag-and-drop" id="blue-box"></div>
<div class="drag-and-drop" id="yellow-box"></div>

ドラッグ&ドロップをしたい要素に指定のクラス名を付けたら後は下の JavaScript と CSS を追加すれば OK です。

JavaScript

(function(){

    //要素の取得
    var elements = document.getElementsByClassName("drag-and-drop");

    //要素内のクリックされた位置を取得するグローバル(のような)変数
    var x;
    var y;

    //マウスが要素内で押されたとき、又はタッチされたとき発火
    for(var i = 0; i < elements.length; i++) {
        elements[i].addEventListener("mousedown", mdown, false);
        elements[i].addEventListener("touchstart", mdown, false);
    }

    //マウスが押された際の関数
    function mdown(e) {

        //クラス名に .drag を追加
        this.classList.add("drag");

        //タッチデイベントとマウスのイベントの差異を吸収
        if(e.type === "mousedown") {
            var event = e;
        } else {
            var event = e.changedTouches[0];
        }

        //要素内の相対座標を取得
        x = event.pageX - this.offsetLeft;
        y = event.pageY - this.offsetTop;

        //ムーブイベントにコールバック
        document.body.addEventListener("mousemove", mmove, false);
        document.body.addEventListener("touchmove", mmove, false);
    }

    //マウスカーソルが動いたときに発火
    function mmove(e) {

        //ドラッグしている要素を取得
        var drag = document.getElementsByClassName("drag")[0];

        //同様にマウスとタッチの差異を吸収
        if(e.type === "mousemove") {
            var event = e;
        } else {
            var event = e.changedTouches[0];
        }

        //フリックしたときに画面を動かさないようにデフォルト動作を抑制
        e.preventDefault();

        //マウスが動いた場所に要素を動かす
        drag.style.top = event.pageY - y + "px";
        drag.style.left = event.pageX - x + "px";

        //マウスボタンが離されたとき、またはカーソルが外れたとき発火
        drag.addEventListener("mouseup", mup, false);
        document.body.addEventListener("mouseleave", mup, false);
        drag.addEventListener("touchend", mup, false);
        document.body.addEventListener("touchleave", mup, false);

    }

    //マウスボタンが上がったら発火
    function mup(e) {
        var drag = document.getElementsByClassName("drag")[0];

        //ムーブベントハンドラの消去
        document.body.removeEventListener("mousemove", mmove, false);
        drag.removeEventListener("mouseup", mup, false);
        document.body.removeEventListener("touchmove", mmove, false);
        drag.removeEventListener("touchend", mup, false);

        //クラス名 .drag も消す
        drag.classList.remove("drag");
    }

})()

classList を使っているため IE10 以上の対応コードです。モダンブラウザであれば問題なく動きます。

CSS

.drag-and-drop {
    cursor: move;
    position: absolute;
    z-index: 1000;
}

.drag {
    z-index: 1001;
}

CSS に関しては最低限のものだけです。ドラッグ中の要素には .drag というクラス名が付くので何らかのスタイルを付けてあげることも出来ます。position を absolute にするので top、left を使って座標を指定してあげることも必要です。

cursor: move で移動可能用のカーソルに変えています。普通のカーソルで良いという場合はその行を削除してください。

デモ

以下の3つの赤青黄のボックスはドラッグ&ドロップで移動可能です。複数あっても移動可能なのがわかるかと思います。

drag
and
drop

まとめ

このデモだけでは何に使えば良いのかわからないような感じですが、例えばモーダルウインドウを自由に動かせるようにしたりするのに使えます。小さいウインドウをたくさん使うような WEB アプリなんかも使えるかもしれません。

これ系のもっとすごいライブラリはたくさんあるのですが基本の部分という事で書いてみました。