前々回のドラッグアンドドロップを応用して、画像ビューワー作りに挑戦しましょう。

サンプルを見る

サンプルは、第9回で使ったサンプルを改造して、画像の領域をドラッグアンドドロップすると、横並びの画像をスライドさせることができるようにしました。

実装する前に

実装の前に、今回のコンテンツの作りについて説明します。 下の図を見てください。

第9回で使ったサンプルをそのまま利用し、図のようにドラッグすると全体がスライドするように作り変えます。 その際、第9回ではループ様に、端の画像を入れ替える処理を入れましたが、今回は無くてもいいでしょう。

つまり、横並びになっている画像を、一つのタグの中に入れてしまい、その要素に対して、ドラッグ処理を入れればいいということになりますので、だい11回のドラッグアンドドロップのソースコードのコピーで、実装できてしまいます。

実装しよう

まずはHTMLのソースから見てみましょう。

<style>
.box
{
    width:400px;
    height:300px;
    position:absolute;
}

#container
{
    position:absolute;
    left:0px;
}

#wrap
{
    position:relative;
    width:400px;
    height:300px;
    margin:0 auto;
    overflow:hidden;
}
</style>

</head>
<body>
<div id="wrap">
    <div id="container">
        <div class="box" id="box0"><img src="0.JPG" width="400" height="300"></div>
        <div class="box" id="box1"><img src="1.JPG" width="400" height="300"></div>
        <div class="box" id="box2"><img src="2.JPG" width="400" height="300"></div>
        <div class="box" id="box3"><img src="3.JPG" width="400" height="300"></div>
        <div class="box" id="box4"><img src="4.JPG" width="400" height="300"></div>
        <div class="box" id="box5"><img src="5.JPG" width="400" height="300"></div>
    </div>
</div>
</body>
</html>

そのまま、第9回のコードですが、一か所だけ違うのが、「.box」が指定された画像を「#container」を指定した「divタグ」で囲っています。 第9回では、「.box」個別に動かしてましたが、今回は画像をひとまとまりの箱に入れて動かします。

次にJavaScriptのソースです。

<script>
var boxArray = new Array();
var width = 400;
var mouseDown = false;
var preX = 0;

$(function ()
{
    //位置を初期化
    for(var i = 0 ; i < 6 ; i++)
    {
    boxArray.push("#box" + i);
    //スライドショーで移動させるため、左にずらしておく
    var xPos = width * i;
    $(boxArray[i]).css("left" , xPos + "px");
    }

    $("#container").mousedown(startFunc);
    $(document).mousemove(moveFunc);
    $(document).mouseup(endFunc);
});

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

/*
ドラッグ判定開始。
移動用の開始点ベクトルを設定
*/
function startFunc(e)
{
    preX = e.clientX;
    mouseDown = true;

    /*画像のドラッグ処理になってしまうのを抑制*/
    if (e.preventDefault) {
        e.preventDefault();
    }
    else {
        e.returnValue = false;
    }
}

/*
ドラッグで移動
*/
function moveFunc(e)
{
    //マウスダウンかタッチ中のみ、移動の計算を行う。
    if(mouseDown)
    {
        var mouseX = e.clientX;
        var NowX = parseInt($("#container").css("left").replace(/px/ , ""));
        var moveX = mouseX - preX;
        var nextX = NowX + moveX;
        $("#container").css("left" , nextX + "px");

    preX = mouseX;
    }
}
</script>

第9回同様、初期化時に画像を横並びに並べます。 次に、ドラッグ処理の実装ですが、これは第11回の物をそのまま流用しています。

唯一違うのが、移動方向がXのみでいいので、Y軸に関する記述は全て削除しています。

これでドラッグでの移動が実装できるはずですが、一つ問題があります。 それは、ドラッグすると、ブラウザのデフォルト動作で、画像のドラッグ処理が実行されてしまうのです。

そこで、うまく画像がドラッグされたという処理をキャンセルしたいです。

イベントのキャンセルは、ブラウザ毎に多少の違いはありますが、きちんと用意されています。 IE系では、イベントオブジェクトのプロパティ「returnValue」に「false」を指定、非IE系では、「preventDefaultメソッド」を実行すれば、指定したイベントハンドラ以外のイベントをキャンセルすることができます。

/*画像のドラッグ処理になってしまうのを抑制*/
if (evt.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}

「mousedownイベント」のイベントハンドラ内に、上記のコードを入れます。 ここでは、「e.preventDefault」が存在すれば、 「preventDefaultメソッド」を実行、なければIE系と見なし、「returnValue」にfalseを設定し、イベントが値を返さないようにします。

タグが多層化した場合、どの要素で実行されたイベントがキャンセルされたかとか、ややこしい話はありますが、今回はイベントを指定する要素が一つだけなので、「イベントのキャンセルは、returnValueとpreventDefalultで出来るんだな」と、覚えてください。

後は、例えばleftに入れる値を監視し、領域外に出ないように、うまく分岐させるなどすれば、さらにコンテンツとして精度が上がるでしょう。

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