前回の画像ビューワーをそのままiPhone、iPad、Androidに対応させましょう。

サンプルを見る

サンプルは、第13回で使ったサンプルを改造して、スマートフォン・タブレットで動作する用に作り変えました。 今回のサンプルは、教材用にシンプルなコードになるように、スマートフォン用のコードしか入れていませんので iOS・Android OS搭載の、スマートフォン・タブレットのみでしか動作しません。 サンプルの動作を確認する際は、必ず対応端末でご覧ください。

タッチについて

前回のサンプルでは、「mousedown」「mousemove」「mouseup」イベントを利用しましたが、これらのイベントを利用したドラッグ&ドロップ処理は、スマートフォンOSではうまく動作しません。 そこで、スマートフォンOS用には、専用のイベントで対応することになります。

そもそもスマートフォンOSは、指で動作する様に作られているので、当然指での操作に即したイベントが用意されています。 それが、「touchstart」「touchmove」「touchend」の各種イベントです。

「touchstart」は、画面にタッチした時、「touchmove」は、タッチ後、指を動かしたとき、「touchend」は指を画面から放したときに発生します。

つまり、前回マウスイベント系で処理していた部分を、全てタッチ系のイベントに置き換えてしまえばいいのです。

実装しよう

HTMLのソースは前回と全く一緒なので、マウス系のイベントとタッチ系のイベントの実装方法の違いを解説します。

まず、タッチ系のイベントは、jQueryのイベント追加処理の「bind」を使うより、JavaScriptのデフォルトの「addEventListener」で実装した方が色々と都合がいいです。

なので、

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

を、

$("#container")[0].addEventListener("touchstart" , startFunc);
$(document)[0].addEventListener("touchmove" , moveFunc);
$(document)[0].addEventListener("touchend" , endFunc);

この様に書きます。

$("#container").addEventListener("touchstart" , startFunc);

上のような書き方だと、jQueryには、「addEventListener」というメソッドは無いためエラーになってしまいます。 「addEventListener」は、必ずHTMLオブジェクトで実行しなくてはいけません。

しかし、通常jQueryのセレクタで取得すると、一旦jQueryオブジェクトという、HTMLオブジェクトを内包したjQuery専用のオブジェクトにしてしまいます。

ですので、「addEventListener」や、その他JavaScript標準メソッドや、あるブラウザ特有の処理を行う場合は、jQueryオブジェクトから、HTMLオブジェクトを取り出す必要があります。

そこで一番簡単なやり方が、「 $("#container")[0] 」なのです。

jQueryでは、HTMLオブジェクトを、セレクタで取得した数分、配列で保持しています。 なので、ひとつしかエレメントが無い場合(id属性など)は、[0]番目を取得すればいいのです。

これで、HTMLでタッチを扱う準備が出来ました。 それでは次に、タッチイベントのイベントハンドラを定義しましょう。

タッチイベントで、タッチした座標を取得するには

e.touches[0].pageX;

と、します。

「e.touches」で、タッチ自体を取得できるのですが、「 e.touches[0].pageX; 」このように、配列のインデックスを渡しています。 実は、スマートフォンのタッチイベントでは、タッチオブジェクトは複数存在します。

何故かというと、スマートフォンは複数の指での操作(マルチタッチ)に対応しているため、JavaScriptのタッチイベントも、マルチタッチ前提で実装されているからです。

なので、そのデバイスで同時に検知可能な本数分だけ、タッチオブジェクトを保持することができます。

なお、配列に入る順番は、指で触った順番になります。

後は、前回のソースで、座標を取得しているところを、全て「 e.touches[0].pageX; 」に置き換えればOKです。 割と簡単ですね。

<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")[0].addEventListener("touchstart" , startFunc);
    $(document)[0].addEventListener("touchmove" , moveFunc);
    $(document)[0].addEventListener("touchend" , endFunc);
});

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

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

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

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

        preX = mouseX;
    }
}
</script>

後は、前回のコードと今回のコードを組み合わせれて、ユーザーエージェントで振り分ければ、ワンソースでPC・スマートフォンに対応できますね。

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