未分類

マルチタッチで処理を分岐する

今回の課題

スマホ用のサイトを作っていて、Canvasに指で絵を書くようなソフトを作っていて、次のような課題が発生しました。

「Canvasを2本指で拡大縮小するしたいのに、Canvasにお絵かきされてしまう」

つまり、Canvasがtouchイベントに反応するため、お絵かきされてしまうのです。Canvasがひとつならいいのですが、今回は複数のCanvasを利用するため、2つのCanvasに2本の指がまたがるとCanvasからはマルチタッチを見分けることができないのです。2本指で操作するときはCanvasにイベントを通知してほしくないのです。実はこれには簡単な解決策がありました。イベントの2つの伝達方法を理解していれば簡単に実装できます。では、まずイベントの伝わり方から解説します。

キャプチャリングとバブリング

Javascriptでイベント処理をする場合に、バブリングと呼ばれる方法を皆さんは使っていると思います。私はjQueryのお世話になっているので、イベントが親要素に伝わっていく(バブリング)仕組みは理解していました。しかし、実はイベントにはキャプチャリングと呼ばれる、親要素から子要素に伝わる流れもあるのです。

歴史的にはネットスケープ社が「イベントは親から子に伝わるんだ」という考えでキャプチャリングという方式を採用しましたが、マイクロソフト社が「イベントは子から親に伝わる」と真っ向から対立してバブリングという方式を採用しました。こんなに逆になっていると標準化が大変なのですが、W3Cの偉い所は、「2つの考えを同時に満たしてしまえ」と考えたところです。

どういうことかというと、例えばbodyの中のbutton要素があるとして、buttonをクリックした場合に次のようになります。

  1. document(先祖)clickイベント発生
  2. body(親)でclickイベント発生
  3. button(本人)でclickイベント発生
  4. body(親)でclickイベント発生
  5. document(先祖)clickイベント発生

まず親から子にまずイベントが伝わり(キャプチャリング)、次いで子から親にイベントが伝わる(バブリング)という仕組みを定義しました。

キャプチャリングの図

バブリングの図

W3Cの定義の図(偉い!)

どう実装するか

さて、この仕組が分かれば簡単ですね。コードは次のようになります。

これで二本指の場合はstopPropagationにより子供に伝わらないようにできます。addEventListner関数の3番目の引数にtrueを入れるとキャプチャリング時のイベント処理、何も入れないかfalseを入れるとバブリング時のイベント処理ができます。

参考

今回の記事はこちらを参考にさせていただきました(図も引用させていただきました)。

http://www.quirksmode.org/js/events_order.html

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です