サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJS次期バージョンのイベントモデル改訂

ID: FN1308004 Technique: HTML5 and JavaScript Library: EaselJS NEXT

EaselJS次期バージョン候補(NEXT)でイベントモデルが大きく変わります。本稿はCreateJS Blogの記事「Event Model Updates」にもとづいて、その中身をご紹介します。イベントモデルは、CreateJSの他のライブラリにも用いられます。イベントがより扱いやすくなり、一貫した仕組みになります。


01 onイベントハンドラ

これまでのCreateJSでは、DisplayObject.onClickなどonで始まるイベントハンドラは使わず、EventDispatcher.addEventListener()メソッドによるリスナーを用いることが勧められていました。それでも残されてはいたonハンドラが、次期バージョンからはすべて除かれます。開発においてイベントモデルがひとつに絞られることで、後述のバブリングなど新たな機能が加えやすくなります。


02 EventDispatcher.on()メソッド

EventDispatcher.addEventListener()メソッドによるイベントリスナーのモデルは堅牢で統一されていて、DOM Level 2イベントモデルと互換性があります。けれど、手間のかかるきらいがあり、機能豊富とはいえません。

そこで、ショートカットとなるEventDispatcher.on()メソッドを加えました(jQueryなどのライブラリにならいました)。このメソッドを使えば、onイベントハンドラと変わらない入力で、堅牢なイベントリスナーが加えられます。しかも、EventDispatcher.on()メソッドで加えたリスナーは、onイベントハンドラと同じく、イベントを配信するオブジェクトがスコープとなって呼出されます。

以下のJavaScriptコードは、いずれもTicker.tickイベントで呼出す関数(myHandler())を定めます。第1行目は、次期バージョンで除かれるonイベントハンドラが用いられています。第2行目が新たなEventDispatcher.on()メソッドを使った場合です。第3行目は、EventDispatcher.addEventListener()メソッドの書き方になります。

初めの2行は見た目はさほど違いません。ただし、2行目は内部的にはEventDispatcher.addEventListener()メソッドを呼出します。イベントで呼出される関数(myHandler)の中のthis参照は、ともにイベントを配信するオブジェクト(obj)になります。第3行目は、メソッドの名前からして長く、リスナー関数のthis参照はグローバルオブジェクトです。

  1. obj.onTick = myHandler;
  2. obj.on("tick", myHandler);
  3. obj.addEventListener("tick", myHandler);

EventDispatcher.on()メソッドには、さらに機能が加わっています。渡せる引数は、つぎに示す6つです。第3引数はリスナー関数のスコープを定めます。第4引数にtrueを渡すと、イベントは1回しか送られません(デフォルト値はfalse)。第5引数に与える値は、リスナー関数がイベントオブジェクトに続く第2引数として受取ります。第6引数は、後述のイベントフローについて、trueがキャプチャの定めとなります(デフォルト値はfalse)。

オブジェクト.on(イベント, リスナー関数, スコープ, 1回かぎり, 渡す値, キャプチャ)

つぎのJavaScriptコードは、オブジェクト(btn)のDisplayObject.clickイベントにリスナー関数(handleClick())を加えます。関数の中のthis参照は、第3引数(myObj)で別のオブジェクトに定められました。また、第4引数(true)により1度しか呼出されません。第5引数("hello!")の値は、リスナー関数の第2引数として渡されます。

  1. btn.on("click", handleClick, myObj, true, "hello!");

EventDispatcher.removeEventListener()に対応するEventDispatcher.off()メソッドも加わります。ただし、後者は内部的に前者のメソッドを参照しています(したがって、引数も同じです)。

気をつけなければならないのは、EventDispatcher.on()メソッドは、第2引数の関数から他の引数の定めに応じた新たな関数(ラッパー)をつくって、リスナーに加えることです。つまり、第2引数の関数をEventDispatcher.removeEventListener()メソッドに渡しても、リスナー関数ではないので削除できません。リスナー関数として加えられた新たな関数は、EventDispatcher.on()メソッドから返されます。したがって、その戻り値がイベントリスナーから除くべき関数になります。

  1. clickListener = btn.on("click", handleClick);
    // ...[中略]...
  2. btn.off("click", clickListener);

03 Eventクラス

イベントオブジェクトの基本クラスとしてEventを定めました。ごく単純なイベントを配信するときは、EventDispatcher.dispatchEvent()メソッドにイベントの文字列を渡すのがお勧めです。すると、メソッドの参照するオブジェクトがそのイベントのリスナーをもつ場合にかぎり、Eventクラスのオブジェクトがつくられて送られます。したがって、無駄なインスタンスをつくったり、ガベージコレクションの手間が省けます。

  1. var evt = new Event("myevent");
  2. evt.myEventData = "foo";
  3. this.dispatchEvent(evt);
    // Eventオブジェクトに追加するプロパティがない場合に推奨
  1. this.dispatchEvent("myevent");

04 Event.remove()メソッド

イベントリスナーを簡単に除けるように、EventクラスにEvent.remove()メソッドを備えました。リスナー関数が受取ったEventオブジェクトを参照して呼出せば、実行している関数がイベントリスナーから消せます。たとえば、つぎのコードは、リスナー関数(eventHandler)のカウンタ変数(eventHandler)の値が3を超えると、関数をイベントリスナーから除きます。

  1. function eventHandler(evt) {
  2.   if (this.count++ > 3) {
  3.     evt.remove();
  4.   }
  5. }

前述02でEventDispatcher.on()メソッドについてご説明したとおり、ラッパー関数をリスナーに加えたとき、その削除には注意が要ります。Event.remove()メソッドを使えば簡単に解決できる場合も多いでしょう。


05 EventDispatcherクラスの継承

EventDispatcherクラスは、イベントリスナーを扱うほとんどのクラスが継承することになりました。継承でなく、静的メソッドEventDispatcher.initialize()によるMixin(「EaselJSでイベントリスナーを扱うEventDispatcherクラス」「実装」の[注*1]参照)でメソッドを加えるクラスも、少し残っています。そのひとつに、静的なメソッドでリスナーを扱うTickerクラスが挙げられます。また、MouseEventクラスも、MouseEvent.mouseupMouseEvent.mousemoveイベントが推奨されなくなるため(F-site「EaselJSの次期バージョンにおけるイベントのバブリングとマウスイベント」参照)、Mixinを用いています。


06 イベントのバブリング

CreateJSは、DOM Level 2イベントバブリングモデルをサポートするとになりました。したがって、イベントはEaselJSの表示オブジェクトの階層をとおして伝わります(前出「EaselJSの次期バージョンにおけるイベントのバブリングとマウスイベント」参照)。イベントのバブリングが採入れられたことにより、つぎのようなメソッドやプロパティも備わります。

  • Event.stopPropagation()メソッド
  • Event.stopImmediatePropagation()メソッド
  • Event.preventDefault()メソッド
  • Event.eventPhaseプロパティ
  • Event.cancelableプロパティ
  • Event.currentTargetプロパティ
  • useCapture引数

なお、イベントが表示リストの階層を上る流れがバブリング、下る流れはキャプチャと呼ばれます。こうしたイベントの流れ(フロー)は、おもにEaselJSの表示リストを考えた仕組みです。けれども、EventDispatcherクラスのメソッドを備え、parentプロパティをもつオブジェクトであれば使えます。


07 EaselJSの新たなイベント

EaselJSのDisplayObjectクラスには、つぎのようなイベントが新たに加わります。

  • DisplayObject.rolloverイベント
  • DisplayObject.rolloutイベント
  • DisplayObject.pressmoveイベント
  • DisplayObject.pressupイベント

後のふたつのイベントは、ターゲットのオブジェクト上でマウスボタンを押したままマウスポインタを動かし、さらにマウスボタンを放したときに起こります。これらのイベントが加わったことにともなって、MouseEvent.mousemoveおよびMouseEvent.mouseupイベントは使わないよう求められます。

また、Stageクラスにも、つぎのようなイベントが備わります。

  • Stage.mouseleaveイベント
  • Stage.mouseenterイベント
  • Stage.tickstartイベント
  • Stage.tickendイベント
  • Stage.drawstartイベント
  • Stage.drawendイベント


作成者: 野中文雄
作成日: 2013年8月22日


Copyright © 2001-2013 Fumio Nonaka.  All rights reserved.