マルチタッチ ウェブ開発

はじめに

スマートフォンやタブレットなどのモバイル デバイスは通常、静電容量方式のタッチ感知画面を備えており、ユーザーの指による操作をキャプチャします。モバイルウェブが進化し、より高度なアプリケーションを利用できるようにするなか、ウェブ デベロッパーにはこうしたイベントを処理する方法が必要になります。たとえば、ペースの速いゲームでは、プレーヤーは一度に複数のボタンを押す必要があります。タッチスクリーンの場合、これはマルチタッチを意味します。

Apple は iOS 2.0 でタッチイベント API を導入しました。Android はこの事実上の標準に追いついて ギャップを縮めています。最近、W3C 作業グループが集まって、このタッチイベント仕様の作成に取り組んでいます。

この記事では、iOS デバイス、Android デバイス、およびタッチをサポートするハードウェア上のデスクトップ Chrome で提供されるタッチイベント API について詳しく解説し、構築できるアプリケーションの種類、おすすめの方法、タッチ対応アプリケーションの開発を容易にする便利な手法について説明します。

タッチイベント

仕様では、次の 3 つの基本的なタッチイベントがモバイル デバイスに広く実装されています。

  • touchstart: DOM 要素に指が置かれる。
  • touchmove: DOM 要素に沿って指をドラッグする。
  • touchend: DOM 要素から指が離れる。

各タッチイベントには、次の 3 つのタッチリストが含まれます。

  • touches: 現在画面上にあるすべての指のリスト。
  • targetTouches: 現在の DOM 要素上の指のリスト。
  • changedTouches: 現在のイベントに関与している指のリスト。たとえば、touchend イベントでは、削除された指を示します。

これらのリストは、タップ情報を含むオブジェクトで構成されています。

  • 識別子: タッチ セッションで現在の指を一意に識別する番号。
  • target: アクションの対象となった DOM 要素。
  • クライアント、ページ、画面の座標: 操作が行われた画面上の場所。
  • 半径座標と rotationAngle: 指の形状に近似する楕円を記述します。

タップ対応アプリ

touchstarttouchmovetouchend イベントは、ピンチズームや回転などの通常のマルチタッチ操作を含め、ほぼすべての種類のタップベースの操作に対応できる豊富な機能セットを提供します。

次のスニペットでは、1 本指で DOM 要素をドラッグできます。

var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // If there's exactly one finger inside this element
  if (event.targetTouches.length == 1) {
    var touch = event.targetTouches[0];
    // Place element where the finger is
    obj.style.left = touch.pageX + 'px';
    obj.style.top = touch.pageY + 'px';
  }
}, false);

画面上の現在のタップをすべて表示するサンプルを以下に示します。これは、デバイスの応答性を実感する場合にのみ役立ちます。

フィンガー トラッキング。
// Setup canvas and expose context via ctx variable
canvas.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.touches.length; i++) {
    var touch = event.touches[i];
    ctx.beginPath();
    ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true);
    ctx.fill();
    ctx.stroke();
  }
}, false);

デモ

Paul Irish 氏らによるキャンバス ベースの描画デモなど、多くの興味深いマルチタッチ デモがすでに公開されています。

図形描画のスクリーンショット

Browser Ninja は、CSS3 の変換、遷移、キャンバスを使用した Fruit Ninja のクローンである技術デモです。

ブラウザ忍者

おすすめの方法

ズームを防止する

スワイプやジェスチャーはスクロールやズームなどのブラウザの動作と関連していることが多いため、デフォルト設定はマルチタッチには適していません。

ズームを無効にするには、次のメタタグを使用して、ユーザーが拡大縮小しないようにビューポートを設定します。

<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no>

ビューポートの設定について詳しくは、こちらのモバイル HTML5 に関する記事をご覧ください。

スクロールを防止する

一部のモバイル デバイスには、タッチ移動のデフォルト動作があります。たとえば、古典的な iOS のオーバースクロール効果では、スクロールがコンテンツの境界を超えるとビューがバウンドします。これは多くのマルチタッチ アプリでは混乱を招くため、簡単に無効にできます。

document.body.addEventListener('touchmove', function(event) {
  event.preventDefault();
}, false); 

慎重にレンダリングする

複雑なマルチフィンガー ジェスチャーを使用するマルチタッチ アプリを作成する場合は、一度に多数のタッチイベントを処理するため、タッチイベントへの反応に注意してください。画面上にすべてのタッチを描画する前のセクションのサンプルについて考えてみましょう。タップ入力があるとすぐに描画できます。

canvas.addEventListener('touchmove', function(event) {
  renderTouches(event.touches);
}, false);

ただし、この手法では、画面上に指の数が増えることはありません。 代わりに、すべての指をトラッキングしてループでレンダリングすると、パフォーマンスが大幅に向上します。

var touches = []
canvas.addEventListener('touchmove', function(event) {
  touches = event.touches;
}, false);

// Setup a 60fps timer
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

targetTouches と changedTouches を使用する

event.touches は、DOM 要素のターゲットにある指だけではなく、画面に接触しているすべての指の配列です。代わりに event.targetTouches または event.changedTouches を使用する方がはるかに便利な場合があります。

最後に、モバイル向けの開発を行っている場合は、Eric Bidelman の記事とこちらの W3C ドキュメントで取り上げられている、一般的なモバイルのベスト プラクティスにも注意してください。

デバイスのサポート

残念ながら、タップイベントの実装では完全性と品質が大きく異なります。サポートされているイベントや touchmove の呼び出し解像度など、Touch API の実装に関する基本情報を表示する診断スクリプトを作成しました。Nexus One と Nexus S では Android 2.3.3、Xoom では Android 3.0.1、iPad と iPhone では iOS 4.2 をテストしました。

簡単に言うと、テスト済みのブラウザはすべて touchstarttouchendtouchmove イベントをサポートしています。

仕様では追加で 3 つのタッチイベントがサポートされていますが、テスト済みのブラウザではこれらはサポートされていません。

  • touchenter: 動いている指が DOM 要素に入る。
  • touchreach: 動いている指が DOM 要素から離れる。
  • touchcancel: タップが中断される(実装固有)。

各タッチリストの中で、テスト済みのブラウザは touchestargetToucheschangedTouches タッチリストも提供しています。ただし、テスト済みのブラウザは、画面に触れる指の形状を指定する radiusX、radiusY、rotationAngle をサポートしていません。

touchmove 中には、テスト済みのすべてのデバイスで 1 秒間に約 60 回イベントが発生します。

Android 2.3.3(Nexus)

Android Gingerbread ブラウザ(Nexus One と Nexus S でテスト済み)では、マルチタッチはサポートされていません。これは既知の問題です。

Android 3.0.1(Xoom)

Xoom のブラウザは、基本的なマルチタッチに対応していますが、単一の DOM 要素でのみ機能します。ブラウザは、異なる DOM 要素で同時に 2 つのタッチがあっても正しく応答しません。つまり、以下は 2 つの同時タッチに反応します。

obj1.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.targetTouches; i++) {
    var touch = event.targetTouches[i];
    console.log('touched ' + touch.identifier);
  }
}, false);

ただし、以下は対象外です。

var objs = [obj1, obj2];
for (var i = 0; i < objs.length; i++) {
  var obj = objs[i];
  obj.addEventListener('touchmove', function(event) {
    if (event.targetTouches.length == 1) {
      console.log('touched ' + event.targetTouches[0].identifier);
    }
  }, false);
}

iOS 4.x(iPad、iPhone)

iOS デバイスはマルチタッチに完全対応しており、多数の指をトラッキングでき、ブラウザで非常にレスポンシブなタッチ エクスペリエンスを提供します。

デベロッパー ツール

モバイル開発では、多くの場合、パソコンでプロトタイピングを開始し、サポートするデバイスでモバイル固有の部分に取り組む方が簡単です。マルチタッチは、ほとんどの PC にはタップ入力がないため、PC ではテストが難しい機能の一つです。

モバイルでのテストが必要になると、すべての変更をサーバーにプッシュしてからデバイスにロードする必要があるため、開発サイクルが長くなる可能性があります。タブレットやスマートフォンにはウェブ デベロッパー ツールがないため、実行したアプリのデバッグはほとんど不可能です。

この問題の解決策は、開発マシンでタッチイベントをシミュレートすることです。シングルタッチの場合、マウスイベントに基づいてタッチイベントをシミュレートできます。最新の Apple MacBook などのタップ入力を備えたデバイスを使用している場合、マルチタッチ イベントをシミュレートできます。

シングルタッチ イベント

デスクトップでシングルタッチ イベントをシミュレートしたい場合、Chrome のデベロッパー ツールにはタッチイベントのエミュレーションが用意されています。デベロッパー ツールを開き、歯車アイコンを選択して [オーバーライド] または [エミュレーション] を選択し、[タッチイベントのエミュレーション] をオンにします。

その他のブラウザでは、Phantom Limb をぜひお試しください。Phantom Limb は、ページのタッチイベントをシミュレートして、大きな手の動きで起動します。

プラットフォーム間でタップイベントとマウスイベントを統合する Touchable jQuery プラグインもあります。

マルチタッチ イベント

マルチタッチ トラックパッド(Apple MacBook や MagicPad など)上のブラウザでマルチタッチ ウェブ アプリケーションを動作できるようにするために、MagicTouch.js ポリフィルを作成しました。トラックパッドからタッチイベントをキャプチャして、標準のタッチイベントに変換します。

  1. npTuioClient NPAPI プラグインを ~/Library/Internet Plug-Ins/ にダウンロードしてインストールします。
  2. Mac の MagicPad 用の TongSeng TUIO アプリをダウンロードして、サーバーを起動します。
  3. MagicTouch.js をダウンロードします。これは、npTuioClient コールバックに基づいて仕様に対応したタッチイベントをシミュレートする JavaScript ライブラリです。
  4. 次のように、magictouch.js スクリプトと npTuioClient プラグインをアプリケーションに含めます。
<head>
  ...
  <script src="/path/to/magictouch.js"></script>
</head>

<body>
  ...
  <object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
    Touch input plugin failed to load!
  </object>
</body>

プラグインの有効化が必要になる場合があります。

magictouch.js を使用したライブデモは、paulirish.com/demo/multi にあります。

この方法は Chrome 10 でのみテストしましたが、わずかな調整で他の最新のブラウザでも動作するはずです。

コンピュータにマルチタッチ入力がない場合は、reacTIVision などの他の TUIO トラッカーを使用してタッチイベントをシミュレートできます。詳細については、TUIO プロジェクトのページをご覧ください。

ユーザーの操作は、OS レベルのマルチタッチ操作と同じである場合があります。 OS X では、[システム環境設定] の [トラックパッド設定] ペインで、システム全体のイベントを設定できます。

マルチタッチ機能がモバイル ブラウザで広くサポートされるようになるにつれ、新しいウェブ アプリケーションがこの豊富な API を最大限に活用できることを楽しみにしています。