サイトトップ

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

Scripting with CreateJS Suite

Chapter 02 CreateJS Suiteを使う

□02-01 EaselJSを使った描画とアニメーション

CreateJS Suiteの中でも、描画やアニメーション、そしてインタラクションといった中心的な役割を担うのがEaselJSです。本節では、簡単な描画とアニメーションの基本について学びます。


○02-01-01 EaselJSを構成するJavaScriptファイル

本書ではライブラリファイル、ここではEaselJSライブラリがHTMLドキュメントと同じ場所に置かれているものとします(図02-01-001)。EaselJSライブラリのフォルダ(フォルダ名easeljs)の中はさらに機能によってフォルダ分けされ、それぞれにJavaScript(JS)ファイルが納められています。

図02-01-001■EaselJSライブラリのフォルダの中身
[【変更】画像]

easeljsフォルダの中は、機能によってフォルダ分けされ、JavaScriptファイルが納められている。

たとえば、displayフォルダには、Canvasに表示されるオブジェクトに関わるJavaScript(JS)ファイルがまとめられています(表02-01-001)。ライブラリの中のどのJavaScriptファイルが用いられるかは、コンテンツによって変わります。script要素で読込むのは使うJavaScriptファイルだけで構いません。

表02-01-001■EaselJSライブラリの中のフォルダとJavaScriptファイル
フォルダ JSファイル
display Bitmap.js
BitmapAnimation.js
Container.js
DisplayObject.js
DOMElement.js
Graphics.js
MovieClip.js
Shadow.js
Shape.js
SpriteSheet.js
Stage.js
Text.js
events EventDispatcher.js[【削除】(追加予定)]
MouseEvent.js
filters AlphaMapFilter.js
AlphaMaskFilter.js
BoxBlurFilter.js
ColorFilter.js
ColorMatrix.js
ColorMatrixFilter.js
Filter.js
geom Matrix2D.js
Point.js
Rectangle.js
ui ButtonHelper.js[【削除】(追加予定)]
Touch.js
utils [【挿入】Log.js]
SpriteSheetBuilder.js
SpriteSheetUtils.js
Ticker.js
UID.js

それぞれのJavaScriptファイルは、クラスを定義しています。たとえば、次項で用いるStageオブジェクトは、Stageクラスからつくられます。そのためには、JavaScriptファイルStage.jsをscript要素で読込まなければなりません。

このとき、オブジェクト指向プログラミングのクラスには、継承という仕組みがあります(Word 02-01-001「継承」参照)。StageクラスはContainerクラスを継承し、ContainerクラスはさらにDisplayObjectクラスを継承しています。そのため、Stageオブジェクトを使うには、Container.jsとDisplayObject.jsも読込まなければならないのです。

Word 02-01-001■継承

「継承」とは、オブジェクト指向プログラミングで、すでにあるクラスはそのままに、そのクラスに追加・拡張した新たなクラスを定義するとことです。もとになるクラスを「スーパークラス」(super class)または「基本クラス」、新たに定めたクラスを「サブクラス」(sub class)あるいは「派生クラス」と呼びます。

スーバークラスのプロパティやメソッドは、すべてサブクラスに受継がれます。したがって、サブクラスは追加・拡張するプロパティやメソッドの定義をつけ加えればよいのです。しかも、スーパークラスそのものにはまったく手が加わりませんので、同じスーパークラスを継承する他のサブクラスへの影響は気にせずに済みます。


○02-01-02 Stageオブジェクトと表示リスト

EaselJSは、Canvasに表示されるオブジェクトに親子の入れ子関係をつくり、その階層全体を「表示リスト」(display list)としてまとめます。表示リストはアニメーションやインタラクションを扱うのに都合の良い仕組みで、Adobe Flashから採入れられました。表示リストの頂点はStageオブジェクトで、ベクターグラフィックスの描けるShapeやビットマップを納めたBitmapといったオブジェクトのほか、子オブジェクトがもてるContainerオブジェクトによりツリー構造をなします(図02-01-002)。

図02-01-002■Stageオブジェクトを頂点に表示リストの階層がつくられる

Shapeオブジェクトにはベクターグラフィックスが描け、Bitmapオブジェクトはビットマップが納められる。また、Containerオブジェクトは子オブジェクトがもてる。

JavaScriptコードでcanvas要素を取得したら、つぎに表示リストの頂点になるStageオブジェクトをCanvasにつくります。Stage()コンストラクタには、引数としてcanvas要素を渡します(Syntax 02-01-001)。

new Stage(canvas要素)
Syntax 02-01-001■Stageオブジェクトをつくる
Stage()コンストラクタ
文法 Stage(canvas)
概要 表示リストの頂点となる新たなStageオブジェクトをCanvasにつくる。
引数 canvas − Stageオブジェクトの表示リストに加えられた子インスタンスを描くcanvas要素。

Stageオブジェクトをつくる前に、EaselJSライブラリから読込むJavaScriptファイルを確かめておきましょう。つぎの[【変更】6→7]つのクラスが必要になります。なお、最初のscript要素(第1〜3行目)に書かれたJavaScriptコードについては、次項で改めてご説明します。

[【挿入】6]
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/events/EventDispatcher.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>

Stageクラス[【変更】→と]継承するスーパークラスDisplayObjectとContainerのほかに(第[【変更】7〜9→8〜10]行目)、[【変更】3→4]つのクラスUIDとMatrix2D[【挿入】、EventDispatcher、]およびMouseEventが加わっています(第4〜[【変更】6→7]行目)。初めの[【変更】ふた→3]つのクラスUIDとMatrix2D[【挿入】、およびEventDispatcher]は、DisplayObjectクラスが初期化されるとき内部的に用いられます。そして、DisplayObjectクラスの初期化で使うためには、これらのクラスは先に読込まれていなければなりません。継承するクラスについても、スーパークラスはサブクラスより前に読込みます。このようにscript要素を書く順序にも気をつけましょう。[【挿入】なお、MouseEventクラスはStageクラスで用いられます。]

Tips 02-01-001■クラスUIDとMatrix2D[【挿入】およびEventDispatcher]はDisplayObjectクラスで使われる

クラスUIDとMatrix2D[【挿入】、およびEventDispatcher]は、DisplayObjectクラスの中で内部的に使われます(図02-01-003)。DisplayObjectクラスは、Stageオブジェクトも含めたCanvasに表示されるオブジェクトのスーパークラスですので、EaselJSでは必ず用いられます。したがって、クラスUIDとMatrix2D[【挿入】、およびEventDispatcher]もつねにscript要素で読込むことになります。

図02-01-003■DisplayObjectクラスの中で使われているUIDとMatrix2D[【挿入】およびEventDispatcher]クラス
[【変更】画像]


DisplayObject()コンストラクタが呼出すinitialize()メソッドの中で、UID.get()メソッドとMatrix2D()コンストラクタ[【挿入】、およびEventDispatcher.initialize()メソッド]が呼出されている。

MouseEventクラスは、Stageオブジェクトがマウスの動きを調べるために用いられます。Stageクラスの初期化に使われる訳ではありませんので、読込みの順序はさほど気にしなくてよいでしょう(念のため、Stageクラスより前に書きました)。

Stageオブジェクトをつくるscript要素は、つぎのコード02-01-001のとおりです。もっとも、これだけではCanvasには何も表示されませんので、Stageオブジェクトができたことをalert()メソッドで確かめています(第[【変更】15→16行目)。警告ダイアログボックスには[Stage (name=null)]と示されます(図02-01-004)。

コード02-01-001■Stageオブジェクトをつくる
[【挿入】6]
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/events/EventDispatcher.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>
  11. <script type="text/javascript">
  12. var stage;
  13. function initialize() {
  14.   var canvasObject = document.getElementById("myCanvas");
  15.   stage = new Stage(canvasObject);
  16.   alert(stage);   // 確認用
  17. }
  18. </script>

図02-01-004■警告ダイアログボックスでStageオブジェクトが示される

Stageオブジェクトができれば、[Stage (name=null)]と示される。

Tips 02-01-002■Stage()コンストラクタにcanvas要素のid属性を文字列で渡す

Stage()コンストラクタの引数には、canvas要素の参照でなく、そのid属性を文字列で渡すこともできます。引数がcanvas要素の参照でないときは、Stageクラスは内部的にdocument.getElementById()の引数に渡してcanvas要素の参照を得ます。

したがって、前掲コード02-01-001の第[【変更】13〜14→14〜15]行目は、つぎのように1行のステートメントで書くこともできます。

[【変更】行番号]
    // var canvasObject = document.getElementById("myCanvas");
    // stage = new Stage(canvasObject);

  1. stage = new Stage("myCanvas");

○02-01-03 コンパクト版と新バージョン

CreateJSのサイトからダウンロードされるJavaScript(JSファイルには、ライブラリのクラスごとに分けられたものとは別に、ライブラリをひとつのファイルにまとめたコンパクト版(compressed version)があります。コンパクト版のJSファイルは、libフォルダに納められています(図02-01-005)。

図02-01-005■libフォルダに納められたEaselJSライブラリのコンパクト版JavaScriptファイル

ひとつのJSファイルにEaselJSライブラリのクラスほぼすべてが含まれている。

たとえば、EaselJSライブラリのコンパクト版JavaScriptファイルをscript要素で読込めば、ライブラリのクラスをひとつひとつ読込む手間が省けます。しかも、クラスの順序など気にする必要がありません。公開するコンテンツでは、このコンパクト版のJSファイルを用いた方が楽でしょう。

<!--
<script src="easeljs/utils/UID.js"></script>
<script src="easeljs/geom/Matrix2D.js"></script>
<script src="easeljs/events/MouseEvent.js"></script>
<script src="easeljs/display/DisplayObject.js"></script>
<script src="easeljs/display/Container.js"></script>
<script src="easeljs/display/Stage.js"></script>
-->

<script src="lib/easeljs-0.5.0.min.js"></script>

Tips 02-01-003■コンパクト版のJavaScript(JS)ファイル

コンパクト版のJSファイルは使うのに手軽ではあるものの、要らないクラスまで読込むことになります。そこで、コンパクト版のJavaScriptコードは識別子を短くし、スペースや改行などの空白文字もできるかぎり省かれています(図02-01-006)。反面、スクリプトはきわめて読みづらくなっています。

図02-01-006■EaselJSライブラリのコンパクト版JavaScriptファイル

識別子を短くし、スペースや改行などの空白文字もできるかぎり省いている。

クラスの実装を調べるには、クラスごとのJavaScript(JS)ファイルを開けてみるのがよいでしょう。

けれど本書では、スクリプトでCreateJS Suiteのどのクラスを使っているのか確かめ、必要に応じてそれぞれのクラスの中身(実装)を研究できるように、クラスは個別に読込むことにします。なお、本書執筆時に最新のEaselJSは、バージョン0.5.0です(前掲図02-01-005参照)。

Version 0.5.0 [Aug 24, 2012]
****************************************************************************************************
- moved all classes into a configurable createjs namespace
- added support for multitouch
- complete rewrite of drawing model to use a hybrid approach (save/restore & matrix)
- added DisplayObject.mask
...[後略]...

現行のCreateJS Suiteでは、[【変更】前の→古い]バージョンからひとつ大きな仕様変更が加えられています。それは名前空間の追加です。具体的には、CreateJS Suiteのすべてのクラスは、デフォルトでは名前空間createjsをつけて参照しなければなりません。前掲コード02-01-001でStageクラスのコンストラクタ呼出しによりインスタンスをつくるステートメント(第[【変更】14→15]行目)は、新しいバージョンの書き方ではつぎのようになります。

[【変更】行番号]
    //   stage = new Stage(canvasObject);
  1.   stage = new createjs.Stage(canvasObject);

クラスの参照にいちいち名前空間をつけるのは、一見煩わしく感じられるでしょう。けれど、数多くのライブラリを使ったとき、複数のライブラリでたまたまクラスの名前が重複して使えなくなるという問題を防げるのです。

Word 02-01-002■名前空間

名前空間」(namespace)は、数多くの名前(識別子)があるとき、それらを分類してまとめた集合です。プログラミングでは、その集合に名前(識別子)をつけて扱います。

数多くのライブラリを使うと、別のライブラリにたまたま同じ名前のクラスが定められているかもしれません。すると、そのふたつのクラスをともに使うことはできなくなります。クラスに名前空間をつけることにより、このような名前の重複が防げるのです。

もっとも、ライブラリはCreateJS Suiteしか使っていないとか、他のライブラリを用いていても名前の重複がないとわかっている場合もあるでしょう。そういうとき、名前空間が省けると便利です。それだけでなく、名前空間のないCreateJSでつくったこれまでのスクリプトや参考にしたいサンプルが、新しいバージョンのクラス(JSファイル)に置換えるとたちまち動かなくなってしまうのです。

そのため、CreateJS Suiteは、名前空間が変えられる仕組みを採入れました。その仕組みを使って、CreateJS Suiteライブラリをscript要素で読込む前に、名前空間(createjs)をWindowオブジェクトに設定してしまえばよいのです。すると、名前空間に初期化されたクラスはWindowオブジェクトにも納められるので、名前空間を省いても参照できます。

<script>
var createjs = window;
</script>
<script src=CreateJS Suiteのライブラリ></script>

このscript要素を加えれば、古いバージョンで書いたコードやサンプルに新しいCreateJS Suiteのライブラリを読込んでも、これまでどおりクラスが名前空間(createjs)なしに参照できるるので正しく動きます。また、このscript要素は、名前空間が備わる前のライブラリを使っているコードに加えてもとくに問題は生じません。つまり、新旧どちらのCreateJS Suiteでも使えるのです。

本書ではCreateJS Suiteのこれまでのバージョンとの互換性を保ち、公開されているサンプルなどがそのまま動くように、このscript要素を加えることにします(前掲コード02-01-001第1〜3行目)。ただし、他のライブラリを使うとき、クラス名の重複には注意しなければなりません。

もっとも、これから先CreateJS以外にも多くのライブラリを使う場合に備えて、新しい書き方に慣れておくことも大切でしょう。そこで、各節ごとにひとつ、まとめとなるようなコードを選んで、「Namespace」という欄に名前空間createjsをつけたコードに書替えて掲げます。


○02-01-04 ShapeオブジェクトをStageオブジェクトの表示リストに加える

それでは、Stageオブジェクトの表示リストにShapeオブジェクトを子として加えます。Shapeオブジェクトには、次項でベクターグラフィックスを描きます。インスタンスはお約束どおり、Shape()コンストラクタでつくります(Syntax 02-01-002)。オプションの引数は、ここでは省きます。

new Shape()

Stageクラスは、表示リストをもつContainerクラスのサブクラスです。子(DisplayObject)インスタンスを表示リストに加えるには、Container.addChild()メソッドを呼出します。メソッドの引数は子インスタンスです(Syntax 02-01-002)。

親オブジェクト.addChild(子オブジェクト)
Syntax 02-01-002■Shapeオブジェクトを表示リストに加える
Shape()コンストラクタ
文法 Shape(graphics)
概要 新たなShapeオブジェクトをつくる。
引数 graphics − Shapeインスタンスに表示するGraphicsオブジェクト。引数を省くと、新たなGraphicsオブジェクトがつくられる。
Shape.graphicsプロパティ
文法 Shapeオブジェクト.graphics
プロパティ値 Shapeインスタンスに表示するGraphicsオブジェクト。
Container.addChild()メソッド
文法 Containerオブジェクト.addChild(child)
概要 インスタンスを表示リストに加える。重ね順は、すでに加えられている子インスタンスの最前面に置かれる。複数の子インスタンスを第2引数以降に順に加えることもできる。
引数 child − 子として表示リストに加えるDisplayObjectインスタンス。
戻り値 子として加えたDisplayObjectインスタンス。複数のインスタンスを引数に与えたときは、最後(最前面)の子インスタンス。
Container.removeChild()メソッド
文法 Containerオブジェクト.removeChild(child)
概要 子インスタンスを表示リストから除く。
引数 child − 表示リストから除くDisplayObjectインスタンス。
戻り値 子インスタンスがあって削除できればtrue、見つからないときはfalseを返す。

以下のコード02-01-002は、新たにつくったShapeインスタンスを、Container.addChild()メソッドでStageオブジェクトの表示リストに加えます(第[【変更】17〜18→18〜19]行目)。もっとも、Shapeオブジェクトにはまだベクターグラフィックスが描かれていませんので、Canvasには何も表れません。そこで、alert()メソッドでインスタンスができたことを確かめています(第[【変更】19→20]行目)。

DisplayObject.parentプロパティは、表示リストにおける親オブジェクトを参照します。したがって、警告ダイアログボックスには、ShapeオブジェクトとStageオブジェクトの存在が示されます(図02-01-007)。

コード02-01-002■Stageオブジェクトの表示リストにShapeインスタンスを加える
[【挿入】6]
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/events/EventDispatcher.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>
  11. <script src="easeljs/display/Graphics.js"></script>
  12. <script src="easeljs/display/Shape.js"></script>
  13. <script>
  14. var stage;
  15. function initialize() {
  16.   var canvasElement = document.getElementById("myCanvas");
  17.   stage = new Stage(canvasElement);
  18.   var myShape = new Shape();
  19.   stage.addChild(myShape);
  20.   alert([myShape, myShape.parent]);   // 確認用
  21. }
  22. </script>

図02-01-007■警告ダイアログボックスにShapeとStageオブジェクトが示される

ShapeとStageオブジェクトが、それぞれ[Shape (name=null)]、[Stage (name=null)]と示される。

なお、前掲コード02-01-002は、script要素でShapeクラスに加えてGraphicsクラスも読込んでいます(第[【変更】10〜11→11〜12]行目)。これは、Shapeオブジェクトの中には必ず、ベクターグラフィックスを描くためのGraphicsオブジェクトが含まれるからです。なお、ShapeインスタンスがもつGraphicsオブジェクトは、Shape.graphicsプロパティで参照できます(前掲Syntax 02-01-002)。

[*筆者用参考]
Flash Professional Toolkit for CreateJSのファーストステップガイド

より複雑なプロジェクトでは、exportRootを取り除き、ステージに要素を直接追加するでしょう。これにより、表示リストからレイヤーが1つ削除されます。この結果、要素が参照しやすくなり、わずかですが、パフォーマンスが向上します。

○02-01-05 Graphicsオブジェクトにベクターグラフィックスを描く

では、Shapeインスタンスから取出したGraphicsオブジェクトに、塗りと線のついた円を描いてみます。まず、ShapeインスタンスのもつGraphicsオブジェクトは、前述のとおりShape.graphicsプロパティで参照が得られます(前掲Syntax 02-01-002)。

ベクターグラフィックスの線と塗りは、それぞれGraphics.beginStroke()Graphics.beginFill()メソッドにより定めます。引数はともに色を指定する文字列です。円はGraphics.drawCircle()メソッドで描きます。引数は3つの数値で、円の中心のxy座標と半径です(Syntax 02-01-003)。

Syntax 02-01-003■Graphicsオブジェクトにベクターグラフィックスを描く
Graphics()コンストラクタ
文法 Graphics()
概要 新たなGraphicsオブジェクトをつくる。
引数 なし。
Graphics.beginStroke()メソッド
文法 Graphicsオブジェクト.beginStroke(color)
概要 定められた色で線を描く。それまでのサブパスは閉じられる。
引数 colorCSSにしたがった色指定の文字列。引数がないときは、線が描かれない。
戻り値 メソッドが呼出されたGraphicsオブジェクト。
Graphics.beginFill()メソッド
文法 Graphicsオブジェクト.beginFill(color)
概要 定められた色で塗る。それまでのサブパスは閉じられる。
引数 colorCSSにしたがった色指定の文字列。引数がないときは、塗られない。
戻り値 メソッドが呼出されたGraphicsオブジェクト。
Graphics.drawCircle()メソッド
文法 Graphicsオブジェクト.drawCircle(x, y, radius)
概要 定められた中心座標と半径で円を描く。
引数 x ー 円の中心となるx座標。
y ー 円の中心となるy座標。
radius ー 円の半径。
戻り値 メソッドが呼出されたGraphicsオブジェクト。
Stage.update()メソッド
文法 Stageオブジェクト.update()
概要 Stageオブジェクトの表示リストに連なる子インスタンスすべてのtick()メソッドを呼出して、それらをCanvasに描画する。
引数 なし。
戻り値 子として加えたDisplayObjectインスタンス。

円の描画は関数(draw())として定めます。引数はShapeオブジェクトです。つぎの関数は、引数のShapeオブジェクトの座標(0, 0)に半径40ピクセルの円を、青い線とシアンの塗りで描きます。なお、ステートメントの行番号は、後に掲げるコード02-01-003にもとづきます。

  1. function draw(myShape) {
  2.   var myGraphics = myShape.graphics;
  3.   myGraphics.beginStroke("#0000FF");
  4.   myGraphics.beginFill("#00FFFF");
  5.   myGraphics.drawCircle(0, 0, 40);
  6.   stage.update();
  7. }

ふたつ説明を補います。第1に、Stage.update()メソッドの呼出しです(第17行目)。Canvasへの描画は負荷の高い処理です。そのため、Canvasを描き替えるには、原則としてStage.update()メソッドを呼出さなければならないのです(前掲Syntax 02-01-003)。

第2に、この関数(draw())で円が描かれる位置です。Stageオブジェクトの表示リストに加えられたShapeインスタンスは、デフォルトではCanvasの座標(0, 0)つまり左上角に置かれます。そのためこのままでは、円の中心がCanvas左上角になり、円の右下1/4しか見えません(図02-01-008)。

図02-01-008■Canvasの左上角を中心として円が描かれた

Stageオブジェクトの表示リストに加えられたShapeインスタンスは、デフォルトではCanvasの座標(0, 0)に置かれる。

円の位置を動かすには、ふたつのやり方が考えられます。ひとつは、Graphics.drawCircle()メソッドに渡す引数のxy座標値を変えることです。けれどもうひとつ、Shapeオブジェクトの座標を動かしてもよいでしょう。

後者は表示リストの強みが活かされます。たとえば、円をアニメーションで動かそうと思ったとき、前者では円をそのたびに違う座標で描き直すことになります。ところが、後者ならスクリプトはShapeオブジェクトの座標を変えるだけでよく、Graphicsオブジェクトに描いたベクターグラフィックスはそのまま使い回せます。

つぎのコード02-01-003は、前掲の円を描く関数(draw())は書替えることなく、Shapeオブジェクトの座標を右下に(50ピクセルずつ)動かしました(第7〜8行目)。これで、円の全体がCanvasの中に描かれます(図02-01-009)。

コード02-01-003■Shapeインスタンスから取出したGraphicsオブジェクトに円を描く
  1. var stage;
  2. function initialize() {
  3.   var canvasElement = document.getElementById("myCanvas");
  4.   stage = new Stage(canvasElement);
  5.   var myShape = new Shape();
  6.   stage.addChild(myShape);
  7.   myShape.x = 50;
  8.   myShape.y = 50;
  9.   draw(myShape);
  10. }
  11. function draw(myShape) {
  12.   var myGraphics = myShape.graphics;
  13.   myGraphics.beginStroke("#0000FF");
  14.   myGraphics.beginFill("#00FFFF");
  15.   myGraphics.drawCircle(0, 0, 40);
  16.   stage.update();
  17. }

図02-01-009■円の描かれたShapeオブジェクトを右下に動かした

ベクターグラフィックスの描画はそのままに、描画されたShapeオブジェクトの位置を動かした。

○02-01-06 スクリプトの構文を変えて書く

CreateJS Suiteのライブラリの構文は工夫されていて、目的や好みに応じてJavaScriptコードの書き方が変えられたりします。前掲コード02-01-003も、つぎのコード02-01-004のように書替えられます。Shape()コンストラクタとGraphicsクラスの描画メソッドについて、呼出し方を変えています。

コード02-01-004■ShapeとGraphicsクラスのメソッドの呼出し方を変えた円の描画
  1. var stage;
  2. function initialize() {
  3.   var canvasElement = document.getElementById("myCanvas");
  4.   stage = new Stage(canvasElement);
  5.   var myGraphics = new Graphics();
      // var myShape = new Shape();
  6.   var myShape = new Shape(myGraphics);
  7.   stage.addChild(myShape);
  8.   myShape.x = 50;
  9.   myShape.y = 50;
      // draw(myShape);
  10.   draw(myGraphics);
  11. }
    // function draw(myShape) {
  12. function draw(myGraphics) {
      /*
      var myGraphics = myShape.graphics;
      myGraphics.beginStroke("#0000FF");
      myGraphics.beginFill("#00FFFF");
      myGraphics.drawCircle(0, 0, 40);
      */
  13.   myGraphics.beginStroke("blue").beginFill("cyan").drawCircle(0, 0, 40);
  14.   stage.update();
  15. }

第1に、Shape()コンストラクタには、引数としてGraphicsオブジェクトが渡せます(前掲Syntax 02-01-002)。そこで、新たなGraphicsインスタンスをつくって、Shape()コンストラクタに渡しました(コード02-01-004第5〜6行目)。そこで、円を描く関数(draw())も、ShapeでなくGraphicsのオブジェクトを直接引数にして呼出すように書替えました(第10および第12行目)。

第2に、Graphicsクラスの描画メソッドは、メソッドが呼出されたGraphicsオブジェクトを返します(前掲Syntax 02-01-003)。すると、ひとつの描画メソッドを呼出した後に、続けてつぎのメソッドが呼出せます(コード02-01-004第13行目)。タイプの手間と行数が減って楽だと思うか、メソッドの羅列が見にくいと捉えるか、それぞれの考えにより書き方が選べます。

あと、細かい点として、Graphicsクラスの描画メソッドにカラーネーム("blue"と"cyan")を引数にして色指定しました。

Tips 02-01-004■矩形を描くメソッド

矩形を描くにはGraphics.rect()メソッドを使います。メソッド名や引数はCanvasのrect()メソッドと同じです。

Graphicsオブジェクト.rect(x座標, y座標, 幅, 高さ)

このメソッドはさらに、ActionScript 3.0と同じdrawRect()というメソッド名で呼出すこともできます。このように、さまざまなユーザー向けに使いやすさの心配りがされているのです。


○02-01-07 ランダムな塗り色で星形を描く

前述01-03-05「星形を描く」では、Canvasの直線のパスで星形をつくりました。しかし、EaselJSのGraphicsクラスには、星形を描くメソッドGraphics.drawPolyStar()がすでに備わっています(Syntax 02-01-004)。このメソッドでランダムな塗り色の星形を描きましょう。

Graphics.drawPolyStar()の引数は多く、5つ渡します。初めの3つ、xy座標と山の半径はよいでしょう。第4引数は、谷の深さを0以上1未満の小数値で定めます。数値が大きいほど、谷が深くなります(図02-01-010)。0を渡すと谷はなくなって、正多角形が描けます。第5引数は、星形を書き始める頂点の角度です。時計の12時の位置をてっぺんにするには、度数で-90を渡します。

Graphicsオブジェクト.drawPolyStar(x座標, y座標, 山の半径, 頂点数, 谷の深さ, 書き始めの角度)
図02-01-010■異なる谷の深さで描かれた5頂点の星形

図001左
0.8

図001中央
0.6

図001右
0

前述のとおり、Graphics.beginStroke()Graphics.beginFill()メソッドには色指定を文字列で渡します(前掲Syntax 02-01-003参照)。けれど、ランダムに決めるには数値の方が扱いやすいです。静的メソッドGraphics.getRGB()を使えば、数値のカラー値をCSS形式の文字列に変えてくれます(Syntax 02-01-004)。たとえば、Graphics.getRGB(0, 0, 255, 0.5)は、"rgba(0,0,255,0.5)"という文字列を返します。この文字列をGraphics.beginStroke()Graphics.beginFill()メソッドに色指定の引数として渡せば、アルファ0.5の青が設定されます。

Syntax 02-01-004■Graphicsオブジェクトへの星形の描画とカラーの指定
Graphics.drawPolyStar()メソッド
文法 Graphicsオブジェクト.drawPolyStar(x, y, radius, sides, pointSize, angle)
概要 定められた中心座標と半径で円を描く。
引数 x ー 形状の中心となるx座標。
y ー 形状の中心となるy座標。
radius ー 形状の中心から頂点までの長さ。
sides ー 星形または正多角形の頂点数
pointSize ー 星形の谷の深さを0以上1未満の数値で定める。0は谷のない正多角形を描く。
angle ー 描き始めの頂点の角度を度数で定める。
戻り値 メソッドが呼出されたGraphicsオブジェクト。
Graphics.getRGB()メソッド
文法 Graphics.getRGB(r, g, b, alpha)
Graphics.getRGB(color, alpha)
概要 [静的] 引数のRGBカラーとアルファをCSSのrgb()形式で指定する文字列が返される。
引数 r ー 赤要素のカラー値を定める0以上255以下の整数。
g ー 緑要素のカラー値を定める0以上255以下の整数。
b ー 青要素のカラー値を定める0以上255以下の整数。
alpha ー 不透明度を定める0以上1以下の整数。引数を省くと完全な不透明(1に相当)になる。
color ー RGBカラー値を定める0以上0xFFFFFF以下の整数。
戻り値 引数によって決まるカラーをCSSのrgb()形式で指定する文字列。

Word 02-01-003■静的プロパティ・メソッド

インスタンスをつくることなく、クラスを直接参照してアクセスするプロパティやメソッド(関数)は、静的(static)プロパティ・メソッド(関数)と呼ばれます。たとえば、Mathクラスの関数や定数はすべて静的です。切捨てのMath.floor()関数や円周率πの定数Math.PIは、クラスを直接参照してアクセスします。なお、定数というのは、値の変わらない特殊なプロパティといえます。

alert(Math.floor(2.5)); // 表示: 2
alert(Math.PI); // 表示: 3.141592653589793

以下のコード02-01-005は、Graphics.drawPolyStar()メソッドにより5頂点の星形を、青い線とランダムな塗り色で描きます(図02-01-011)。ランダムな色指定の文字列は、Graphics.getRGB()メソッドで求めています(第13行目)。ただ、RGBの3つのカラー値を決めるのは手間です。Graphics.getRGB()メソッドには、RGBカラーを整数ひとつで定める構文があります(前掲Syntax 02-01-004)。そこで、カラー値を0以上0xFFFFFF未満の整数で定めて、メソッドの第1引数に渡しました。なお、ランダムな整数の求め方については、前述01-02-04「関数を定義して呼出す」をご参照ください。

コード02-01-005■Graphicsオブジェクトにランダムな塗りの星形を描く
  1. var stage;
  2. function initialize() {
  3.   var canvasElement = document.getElementById("myCanvas");
  4.   stage = new Stage(canvasElement);
  5.   var myShape = new Shape();
  6.   stage.addChild(myShape);
  7.   myShape.x = 50;
  8.   myShape.y = 50;
  9.   draw(myShape.graphics);
  10. }
  11. function draw(myGraphics) {
  12.   var randomNumber = Math.floor(Math.random() * 0xFFFFFF);
  13.   var randomColor = Graphics.getRGB(randomNumber);
  14.   myGraphics.beginStroke("blue");
  15.   myGraphics.beginFill(randomColor);
  16.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  17.   stage.update();
  18. }

図02-01-011■青い線とランダムな塗りで星形が描かれる

塗り色は、0以上0xFFFFFF未満のランダムな整数値を求めて、Graphics.getRGB()メソッドで色指定した。

○02-01-08 インスタンスに回転のアニメーションを加える

前項で描いた星形のインスタンスを、アニメーションで回してみましょう。アニメーションで使うのがTickerクラスです。まず、アニメーションの処理は[【削除】tick()という決まった名前の]関数で定めます。つぎに、その関数[【削除】が定義されたオブジェクト]を、[【挿入】静的メソッド]Ticker.[【変更】addListener()メソッドに渡してaddEventListener()で"tick"というイベントに]登録します(Syntax 02-01-005)。この[【変更】オブジェクト→関数]は「リスナー」と呼ばれます。

  1. アニメーションの処理を[【削除】tick()]関数として定める。
  2. [【変更】tick()→その]関数[【削除】が定義されたオブジェクト]をTicker.[【変更】addListener()addEventListener()]メソッドで[【挿入】"tick"イベントの]リスナーとして登録する。

[【挿入】↓]
Ticker.addEventListener()は静的メソッドですので、Tickerクラスを直接参照して呼出します(前述Word 02-01-003「静的プロパティ・メソッド」参照)。"tick"イベントは一定の間隔で繰返し発生するので、おもにアニメーションで使われます。そのたびに、メソッドの第2引数に渡したリスナー関数が呼出されます。イベントリスナーの仕組みについては、後の02-03節でもう少し詳しくご説明します。

[【挿入】↓]
Ticker.addEventListener("tick", リスナー関数)

前掲コード02-01-005で描いた星のShapeインスタンスを回すには、スクリプトにつぎのような手を加えます。なお、行頭の番号は後にscript要素全体を掲げるコード02-01-006にもとづきます。

[【変更】行番号、26、36]
  1. var myShape;
  2. function initialize() {
  1.   // var myShape = new Shape();
      myShape = new Shape();
  1.   Ticker.addEventListener("tick", rotate);
  2. }
  1. function rotate() {
  2.   myShape.rotation += 5;
  3.   stage.update();
  4. }

まず、アニメーションを扱う関数(tick())でShapeインスタンスが参照できるよう、インスタンスを納める変数のvar宣言は関数の外に出しました(第[【変更】15および第19→16および第20]行目)。つぎに、スクリプトが書かれたWindowオブジェクトをthisキーワードで参照し、Ticker.addListener()メソッドの引数にリスナーとして加えました(第[【変更】25→26]行目)。そして、リスナーのtick()関数は、tickイベントのたびにShapeインスタンスのDisplayObject.rotationプロパティで角度を5度ずつ増やします(第[【変更】35〜38→36〜39]行目)。なお、画面を書替えるために、Stage.update()メソッドを忘れずに呼出します(第[【変更】37→38]行目)。

Syntax 02-01-005■アニメーションを扱うTickerクラスのメソッド
Ticker.[【変更】addListeneraddEventListener]()メソッド
文法 Ticker.[【変更】addListener(listener, pauseable)addEventListener(type, listener)]
概要 [静的] [【変更】tickイベントのリスナーを登録する。リスナーにはtickイベントで呼出すtick()メソッドが定められたオブジェクトか、任意の関数を渡す。tick()メソッドの引数には、直前のイベントからの経過ミリ秒とイベントを一時停止できるかどうかのブール(論理)値が渡される。
→指定したイベントにリスナーを加える。]
引数 [【挿入】type − イベントの名前(種類)を定める文字列。]
listener ー [【変更】リスナーとして加えるインスタンスまたは関数。→イベントの名前(種類)を定める文字列。]
[【削除】pauseable ー falseを渡すと、tickイベントの一時停止はできない。すると、Ticker.setPaused()メソッドでtrueを設定し、一時停止されていても、tickイベントは呼出される。デフォルト値はtrue。]
戻り値 [【変更】なし。→第2引数に受取ったリスナー。]
Ticker.[【変更】removeListenerremoveEventListener]()メソッド
文法 Ticker.[【変更】removeListener(listener, pauseable)removeEventListener(type, listener)]
概要 [静的] 指定[【変更】されたtickイベントのリスナーを削除する→したイベントに加えたそのリスナーを除く]。
引数 [【挿入】type − イベントの名前(種類)を定める文字列。]
listener ー [【変更】リスナーから除くインスタンスまたは関数。→イベントのリスナーから除く関数またはオブジェクト。]
戻り値 なし。
Ticker.getPaused()メソッド
文法 Ticker.getPaused()
概要 [静的] tickイベントを一時停止しているかどうかのブール(論理)値を返す。
引数 なし。
戻り値 一時停止していればture、そうでなければfalseが返される。
Ticker.setPaused()メソッド
文法 Ticker.setPaused(paused)
概要 [静的] trueにすると、一時停止可能なリスナーにはtickイベントが送られなくなる。falseであれば、tickイベントが送られる。デフォルト値はtrue
引数 pausedtickイベントを一時停止する(true)かしない(false)か定めるブール(論理)値。
戻り値 なし。
Ticker.getFPS()メソッド
文法 Ticker.getFPS()
概要 [静的] 設定されたフレームレート(FPS)を返す。
引数 なし。
戻り値 設定された1秒当たりのフレーム数(FPS)またはtickイベント数。
Ticker.getInterval()メソッド
文法 Ticker.getInterval()
概要 [静的] 設定されたtickイベント間隔ミリ秒数を返す。
引数 なし。
戻り値 設定されたtickイベント間隔のミリ秒数(または1000/FPS)を返す。
Ticker.setFPS()メソッド
文法 Ticker.setFPS(frameRate)
概要 [静的] フレームレート(FPS)を設定する。
引数 frameRate ー 設定する1秒当たりのフレーム数(FPS)またはtickイベント数。
戻り値 なし。
Ticker.setInterval()メソッド
文法 Ticker.setInterval(interval)
概要 [静的] tickイベント間隔のミリ秒数を設定する。
引数 なし。
戻り値 設定するtickイベント間隔のミリ秒数(または1000/FPS)。

[【削除】↓]
Ticker.tickイベント
文法 リスナーオブジェクト.tick = function (timeElapsed, paused)
概要 定められた間隔(頻度)で繰返し配信されるイベントで、リスナーオブジェクトの同名の関数もしくはリスナー関数が呼出される。間隔はTicker.setInterval()またはTicker.setFPS()メソッドで変えられる。デフォルト値は50ミリ秒・20FPS。
引数 timeElapsed ー 直前のtickイベントからの経過ミリ秒数。
paused ー tickイベントが一時停止されている(true)かいない(false)かを示すブール(論理)値。
DisplayObject.onTickイベント
文法 DisplayObjectオブジェクト.onTick = function ()
概要 インスタンスのDisplayObject.onTickイベントに定めたハンドラ(コールバック関数)は、Stageオブジェクトが再描画されるたびに呼出される。Stage.update()メソッドが呼出されると、まずStageオブジェクトの表示リストに含まれるすべてのインスタンスにDisplayObject.onTickイベントが起こる。それから、それらのDisplayObjectインスタンスはステージに描かれる。DisplayObject.onTickイベントは表示リストの階層が下の子インスタンスから順に、親インスタンスまで送られる。なお、DisplayObject.onTickイベントを起こすには、予めStageオブジェクトをTicker.addListener()メソッドでリスナーに加えておかなければならない。
引数 なし。ただし、Stage.update()メソッドに引数を渡して呼出すと、その値がハンドラの引数として受取られる。

星のShapeインスタンスを回すアニメーションのscript要素全体は、以下のコード02-01-006のとおりです。ふたつ説明を加えます。第1に、Tickerクラスを使うために、script要素に加えて読込んでいます(第[【変更】8→13]行目)。第2に、アニメーションを実行するtickイベントの間隔を、Ticker.setFPS()メソッド(前掲Syntax 02-01-005)で30FPS(間隔33ミリ秒)に変えてみました[【挿入】(第25行目)]。これで、星のShapeインスタンスが回ります(図02-01-012)。

コード02-01-006■星のShapeインスタンスを回す
[【変更】26、36][【挿入】6]
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/events/EventDispatcher.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>
  11. <script src="easeljs/display/Graphics.js"></script>
  12. <script src="easeljs/display/Shape.js"></script>
  13. <script src="easeljs/utils/Ticker.js"></script>
  14. <script>
  15. var stage;
  16. var myShape;
  17. function initialize() {
  18.   var canvasElement = document.getElementById("myCanvas");
  19.   stage = new Stage(canvasElement);
  20.   myShape = new Shape();
  21.   stage.addChild(myShape);
  22.   myShape.x = 50;
  23.   myShape.y = 50;
  24.   draw(myShape.graphics);
  25.   Ticker.setFPS(30);
  26.   Ticker.addEventListener("tick", rotate);
  27. }
  28. function draw(myGraphics) {
  29.   var randomNumber = Math.floor(Math.random() * 0xFFFFFF);
  30.   var randomColor = Graphics.getRGB(randomNumber);
  31.   myGraphics.beginStroke("blue");
  32.   myGraphics.beginFill(randomColor);
  33.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  34.   stage.update();
  35. }
  36. function rotate() {
  37.   myShape.rotation += 5;
  38.   stage.update();
  39. }

図02-01-012■星のインスタンスが回る

星のShapeインスタンスが、tickイベントで回り続ける。

[【削除】↓]
Tips 02-01-005■Tickerのリスナーに関数を登録する

Ticker.addListener()メソッドの引数には、オブジェクトでなく関数を登録することもできます。その場合、関数名は自由に定められます。たとえば、前掲コード02-01-006はつぎのように書替えても、同じように星のインスタンスが回ります。

  1. function initialize() {
      // Ticker.addListener(this);
  1.   Ticker.addListener(rotate);
  2. }
    // function tick() {
  1. function rotate() {
  2.   myShape.rotation += 5;
  3.   stage.update();
  4. }

[【削除】↓]
Tips 02-01-006■DisplayObject.onTickイベントでインスタンスを回す

Ticker.addListener()メソッドにStageオブジェクトをリスナーとして加えると、その表示リストに加えた子インスタンスにはDisplayObject.onTickイベントが起こります。そのハンドラでインスタンスを回すこともできます。複数のインスタンスに同じ動きをさせたいときに役立ちます。なお、DisplayObject.onTickイベントのハンドラからStage.update()メソッドは呼出さなくて構いません

  1. function initialize() {
      // Ticker.addListener(this);
  1.   Ticker.addListener(stage);
      myShape.onTick = rotate;
  2. }
    // function tick() {
  1. function rotate() {
      // myShape.rotation += 5;
  2.   this.rotation += 5;
  3.   // stage.update();
  4. }

Namespace 02-01-001■コード02-01-006に名前空間を加える

前掲コード02-01-006に名前空間createjsを加えて書替えると、以下のコード02-01-007のようになります。インスタンスをつくるコンストラクタの呼出し(第[【変更】14〜15→16〜17]行目)だけではなく、静的メソッド(第[【変更】20〜21→22〜23]および第[【変更】25→27]行目)にも名前空間createjsをつけなければなりません。

コード02-01-007■星のShapeインスタンスを回す
[【挿入】3〜4【変更】23、33]
  1. <script src="easeljs/utils/UID.js"></script>
  2. <script src="easeljs/geom/Matrix2D.js"></script>
  3. <script src="easeljs/events/EventDispatcher.js"></script>
  4. <script src="easeljs/events/MouseEvent.js"></script>
  5. <script src="easeljs/display/DisplayObject.js"></script>
  6. <script src="easeljs/display/Container.js"></script>
  7. <script src="easeljs/display/Stage.js"></script>
  8. <script src="easeljs/display/Graphics.js"></script>
  9. <script src="easeljs/display/Shape.js"></script>
  10. <script src="easeljs/utils/Ticker.js"></script>
  11. <script>
  12. var stage;
  13. var myShape;
  14. function initialize() {
  15.   var canvasElement = document.getElementById("myCanvas");
  16.   stage = new createjs.Stage(canvasElement);
  17.   myShape = new createjs.Shape();
  18.   stage.addChild(myShape);
  19.   myShape.x = 50;
  20.   myShape.y = 50;
  21.   draw(myShape.graphics);
  22.   createjs.Ticker.setFPS(30);
  23.   createjs.Ticker.addEventListener("tick", rotate);
  24. }
  25. function draw(myGraphics) {
  26.   var randomNumber = Math.floor(Math.random() * 0xFFFFFF);
  27.   var randomColor = createjs.Graphics.getRGB(randomNumber);
  28.   myGraphics.beginStroke("blue");
  29.   myGraphics.beginFill(randomColor);
  30.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  31.   stage.update();
  32. }
  33. function rotate() {
  34.   myShape.rotation += 5;
  35.   stage.update();
  36. }
  37. </script>


作成者: 野中文雄
更新日: 2013年2月4日 新バージョンに合わせて改訂。
更新日: 2012年12月23日 サンプルファイルのリンクを追加。
更新日: 2012年12月7日 Stage()コンストラクタの呼出しを変更。
更新日: 2012年11月29日 表02-01-001に新たなクラスを追加。
更新日: 2012年11月17日 02-01-07でGraphics.drawPolyStar()メソッドの引数の抜けを修正。
更新日: 2012年9月29日 Syntax 02-01-005にDisplayObject.onTickイベントと、その説明となるTips 02-01-006を追加。
更新日: 2012年9月27日 Syntax 02-01-002のContainer.addChild()メソッドに補足。
更新日: 2012年9月10日 02-01-03「コンパクト版と新バージョン」に書替え、Namespace 02-01-001を追加。
更新日: 2012年8月4日 02-01-03「コンパクト版と次期バージョン」を追加。
更新日: 2012年8月2日 仕様変更に備えてコードを追加した。解説中の行番号参照に注意。
作成日: 2012年7月19日


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