今回は、画面上の要素をドラッグアンドドロップしてみましょう。

サンプルを見る

移動について

まずは、2次元座標においての移動について説明します。

上記のボックスが、「left:120px; top:200px;」の位置から「left:220px; top:220px」の位置まで移動するとき、その移動量は、上記の表のように求められます。

次に、実際に移動させる場合は、上記のボックスの「left:top」に移動量を加算すれば、見事移動が実行されます。 また、加算処理を「setInterval」で連続で実行すれば、ボックスをリアルタイムで移動させることができます。

さて、これで、移動に関しては分かりました。 次にドラッグアンドドロップでの移動について考えてみましょう。

これも考え方は一緒です。 マウスを押したときの座標と、移動したときのマウスの移動量を算出し、それをボックスの「left:top」に加算します。 つまり、マウスカーソルの移動量と同じ移動量でボックスを動かすのです。

すると、同じ移動量で移動するわけですから、あたかもマウスカーソルに追従しているように見えるわけです。

では早速ソースコードを見てみましょう。

var mouseDown = false;

var preX = 0;
var preY = 0;

$(function()
{
    $("#box").mousedown(startFunc);
    $(document).mousemove(moveFunc);
    $(document).mouseup(endFunc);
});

/*
ドラッグ終了
マウスダウン・タッチのフラグを解除
*/
function endFunc(e)
{
    mouseDown = false;
}

/*
ドラッグ判定開始。
*/
function startFunc(e)
{
    preX = e.clientX;
    preY = e.clientY;

    mouseDown = true;
}

/*
ドラッグで移動
*/
function moveFunc(e)
{
    //マウスダウンかタッチ中のみ、移動の計算を行う。
    if(mouseDown)
     {
        var mouseX = e.clientX;
        var mouseY = e.clientY;

        var NowX = parseInt($("#box").css("left").replace(/px/ , ""));
        var NowY = parseInt($("#box").css("top").replace(/px/ , ""));

        var moveX = mouseX - preX;
        var moveY = mouseY - preY;

        var nextX = NowX + moveX;
        var nextY = NowY + moveY;

        $("#info").text($("#box").css("left") + ":" + $("#box").css("top"));

        $("#box").css("left" , nextX + "px");
        $("#box").css("top" , nextY + "px");

        preX = mouseX;
        preY = mouseY;
    }
}

まずはマウスイベントを設定します。

$(function()
{
    $("#box").mousedown(startFunc);
    $(document).mousemove(moveFunc);
    $(document).mouseup(endFunc);
});

マウスイベントは「mousedown」「mousemove」「mouseup」を利用します。

mousedownは、マウスを押したとき、mousemoveは、マウスを動かしたとき、mouseupは、マウスを離したときにそれぞれ発生します。

では、それぞれのイベントハンドラの中身をチェックしましょう。

/*
ドラッグ判定開始。
*/
function startFunc(e)
{
    preX = e.clientX;
    preY = e.clientY;

    mouseDown = true;
}

マウスを押したら、「preX」 「preY」に、押したときのマウス座標を代入し、「mosueDown」フラグを「true」に設定します。 このフラグが「true」の間だけ、mousemoveで移動の計算を実行するわけです。 この座標が、上で説明した移動の計算の開始点になります。

/*
ドラッグで移動
*/
function moveFunc(e)
{
    //マウスダウンかタッチ中のみ、移動の計算を行う。
    if(mouseDown)
     {
        var mouseX = e.clientX;
        var mouseY = e.clientY;

        var moveX = mouseX - preX;
        var moveY = mouseY - preY;

        var NowX = parseInt($("#box").css("left").replace(/px/ , ""));
        var NowY = parseInt($("#box").css("top").replace(/px/ , ""));

        var nextX = NowX + moveX;
        var nextY = NowY + moveY;

        $("#info").text($("#box").css("left") + ":" + $("#box").css("top"));

        $("#box").css("left" , nextX + "px");
        $("#box").css("top" , nextY + "px");

        preX = mouseX;
        preY = mouseY;
    }
}

次にドラッグの処理です。 ドラッグすると、「mosueDown」フラグが「true」の時だけ、処理を実行します。

処理としては、「mouseX」「mouseY」という変数を宣言して、現在のマウス座標を代入します。 次に、移動量を求めます。

var moveX = mouseX - preX;
var moveY = mouseY - preY;

上記の式で、「移動後の座標 - 移動前の座標」というになるので、移動量が求められます。 あとは、下記処理で、ボックスの「left:top」にそれぞれ移動量を足してあげます。

var NowX = parseInt($("#box").css("left").replace(/px/ , ""));
var NowY = parseInt($("#box").css("top").replace(/px/ , ""));

var nextX = NowX + moveX;
var nextY = NowY + moveY;

$("#info").text($("#box").css("left") + ":" + $("#box").css("top"));

$("#box").css("left" , nextX + "px");
$("#box").css("top" , nextY + "px");

まずは、ボックスの「leftとtop」の値を取得します。 「position:absolute」に設定されているので、leftとtopはそれぞれ。xとyに当たります。 ただ、ここで気を付けないといけないのが、left、topの値を取得すると、「100px」のように文字列で返ってきます。

ですので、

「var NowX = parseInt($("#box").css("left").replace(/px/ , ""));」

この様に、「replaceメソッド」を使って、「"px"」の部分を空文字(「""」)に置き換えます。 そうして取得した値は、文字列になっているので「parseInt」で数値に変換します。

あとは、取得したボックスの「left」「top」の値に移動量を加算してあげればOKです。

仮に、移動量がマイナスの値になった場合は、マイナスの数値の加算はそのまま減算になるので全く問題はありません。

河野 義貴
インハウスのFlashクリエイターとして勤務後、2010年独立。一年間のフリーランス期間を経て、2011年9月にスウィーツアンドストリーム株式会社を設立。主にFlash・HTML5を駆使した、PC・スマートフォン向けインタラクティブコンテンツを中心に活動中。マイナビクリエイターセミナー(WCBセミナー)の講師としてもおなじみ。