マルチタッチ ウェブ開発

はじめに

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

Apple は iOS 2.0 で タップイベント API を導入しました。Android は、この事実上の標準に対応し、そのギャップを埋めてきました。最近、W3C のワーキング グループが集まり、このタッチイベントの仕様に取り組みました。

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

タッチイベント

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

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

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

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

これらのリストは、接触情報を含むオブジェクトで構成されます。

  • identifier: タップ セッション内の現在の指を一意に識別する数値。
  • target: アクションのターゲットだった DOM 要素。
  • クライアント / ページ / 画面の座標: アクションが発生した画面上の場所。
  • radius 座標と 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 変換と遷移、キャンバスを使用したフルーツ ニンジャのクローンであるテクノロジー デモ。

ブラウザ 忍者

ベスト プラクティス

ズームの防止

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

ズームを無効にするには、次の meta タグを使用して、ユーザーがスケーリングできないようにビューポートを設定します。

<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 と changesTouches を使用する

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

最後に、モバイル用のアプリを開発するため、Eric Bidelman の記事W3C のドキュメントに記載されている、一般的なモバイルに関するおすすめの方法を把握しておく必要があります。

デバイスのサポート

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

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

仕様では 3 つの追加のタップイベントが定義されていますが、テストしたブラウザではサポートされていません。

  • touchenter: 移動中の指が DOM 要素に接触した。
  • touchleave: 移動中の指が DOM 要素から離れたとき。
  • touchcancel: タッチが中断された(実装固有)。

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

タッチ移動中、テストしたすべてのデバイスでイベントが 1 秒あたり約 60 回発生します。

Android 2.3.3(Nexus)

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

Android 3.0.1(Xoom)

Xoom のブラウザでは基本的なマルチタッチがサポートされていますが、1 つの 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 をお試しください。ページ上のタップ イベントをシミュレートし、巨大な手も表示されます。

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

マルチタッチ イベント

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

  1. npTuioClient NPAPI プラグインをダウンロードして、~/Library/Internet Plug-Ins/ にインストールします。
  2. Mac の MagicPad 用 TongSeng TUIO アプリをダウンロードして、サーバーを起動します。
  3. JavaScript ライブラリ MagicTouch.js をダウンロードして、npTuioClient コールバックに基づいて仕様互換のタッチイベントをシミュレートします。
  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 を最大限に活用できることを非常に嬉しく思います。