日本時間2013年2月14日に公開されたCreateJSの新バージョンにもとづいて解説する。このレジュメをもとに解説したCreateJS勉強会のUSTREAM録画は「第一回勉強会フォローアップ」で公開されている。なお、リンクしたサンプルのHTMLファイルは、ライブラリをダウンロードしなくて済むよう、CDN(Content Delivery Network)のライブラリを使った。
01 EaselJSでCanvasに星形を描く
EaselJSでCanvasの真ん中に星形を描いてみよう(図001)。
図001■Canvasの真ん中に青い星形を描く
01-01 CanvasにStageオブジェクトをつくる
HTMLドキュメントのbody要素にcanvas要素を加え、id属性にJavaScriptで参照するための名前("myCanvas")をつける。また、body要素のonload属性には、初期設定の関数の呼出し("initialize()")を定めておく。
<body onLoad="initialize()">
<canvas id="myCanvas" width="240" height="180"></canvas>
</body>
HTMLドキュメントのhead要素には、script要素でEaselJSライブラリを読込む(ライブラリは予めダウンロードしておく)。
- <script src="lib/easeljs-0.6.0.min.js"></script>
|
EaselJSを使うには、まずCanvasにステージ(Stageオブジェクト)をつくらなければならない。new演算子でStageクラスのコンストラクタを呼出し、引数にはcanvas要素の参照を渡す。なお、CreateJSのクラスを参照するときは、頭に「名前空間」として「createjs」を添える。
new createjs.Stage(canvas要素)
canvas要素の参照は、document.getElementById()メソッドにidを渡すと得られる(第5行目)。初期設定の関数(initialize())で、Stageオブジェクトをつくった(第6行目)。
- var stage;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- stage = new createjs.Stage(canvasElement);
- }
|
01-02 Stageオブジェクトに加えたShapeインスタンスに星形を描く
描画はShapeインスタンスをつくって行う。new演算子でShapeクラスのコンストラクタを呼出す。
new createjs.Shape()
インスタンスをCanvasに表示するためには、Stageオブジェクトの子に加えなければならない。Stageオブジェクトに対してContainer.addChild()メソッドを呼出し、加えたい子オブジェクトを引数に渡す。
親オブジェクト.addChild(子オブジェクト)
Shapeインスタンスをつくる関数(createShape())は、別に定めた(第11〜17行目)。関数の引数に配置するxy座標を渡すと、つくったインスタンスが返される。そのインスタンスをStageオブジェクトの子に加えている(第8行目)。
- function initialize() {
- var myShape = createShape(canvasElement.width / 2, canvasElement.height / 2);
- stage.addChild(myShape);
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
- }
|
Shapeインスタンスへの描画は、Shape.graphicsプロパティのGraphicsオブジェクトに対して行う。Graphicsオブジェクトに星を描く関数(drawStar())も別に定めた(第18〜21行目)。引数にGraphicsオブジェクトを渡す。
描画の塗りはGraphics.beginFill()メソッドで引数にカラーを定め(第19行目)、星形はGraphics.drawPolyStar()メソッドで描く(第20行目)。星形の谷の深さは、0から1までの数値で定める(図002)。また、起点角は3時の方向がデフォルトの0なので、12時方向であれば-90度とする。
Graphicsオブジェクト.beginFill(カラー)
Graphicsオブジェクト.drawPolyStar(x座標, y座標, 半径, 頂点数, 谷の深さ, 起点角)
図002■異なる谷の深さで描かれた5頂点の星形
EaselJSでステージ(Stageオブジェクト)を描き替えるには、必ずStage.update()メソッドを呼出さなければならない(第9行目)。
Stageオブジェクト.update()
- function initialize() {
- stage.update();
- }
|
つぎのコード001は、Canvasの真ん中にShapeインスタンスを置いて、インスタンスに青い星形を描く(前掲図001参照)。
コード001■EaselJSでCanvasの真ん中に青い星形を描く
- <script src="lib/easeljs-0.6.0.min.js"></script>
- <script>
- var stage;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- stage = new createjs.Stage(canvasElement);
- var myShape = createShape(canvasElement.width / 2, canvasElement.height / 2);
- stage.addChild(myShape);
- stage.update();
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
- }
- </script>
|
02 TweenJSでオブジェクトをトゥイーンアニメーションさせる
TweenJSでShapeインスタンスをトゥイーンアニメーションさせよう。インスタンスはCanvasの上端に置いて(図003)、落ちるアニメーションにする。そのため、Shapeインスタンスの位置を水平方向は真ん中、垂直方向は上端とした(第11行目)。
02-01 星形のShapeオブジェクトをCanvasの上端に置く
図003■星形をCanvas真ん中の上端に描く
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- var nWidth = canvasElement.width;
- var nHeight = canvasElement.height;
- var myShape = createShape(nWidth / 2, 0); // canvasElement.height / 2);
- }
|
02-02 Tweenクラスでオブジェクトにトゥイーンを定める
script要素には、TweenJSライブラリの読込みを加える(第2行目)。
- <script src="lib/tweenjs-0.4.0.min.js"></script>
|
Tweenクラスのコンストラクタには、引数としてトゥイーンアニメーションさせるオブジェクトを渡す。
new createjs.Tween(対象オブジェクト)
オブジェクトのプロパティをトゥイーンするには、Tween.to()メソッドを用いる。第1引数にはトゥイーンするプロパティと値の組を納めたObjectインスタンスを渡す。第2引数はトゥイーンにかける時間で、第3引数はイージングを関数で渡す。イージングの関数は、Easeクラスから選べる。
Tweenオブジェクト.to(プロパティ値のObject, 間隔, イージング関数)
トゥイーンは新たな関数(setTween())で定めることとし、初期設定の関数(initialize())から呼出した(第12行目)。引数には、トゥイーンするオブジェクトと移動先の垂直座標を渡す。
トゥイーン設定の関数(setTween())は、引数のオブジェクトをTween()コンストラクタに渡し(第18行目)、Tween.to()メソッドでy座標の移動と回転(rotation)をプロパティに定めた(第19行目)。イージング関数には、バウンドのように値が変化するEase.bounceOutを選んだ。
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- var nWidth = canvasElement.width;
- var nHeight = canvasElement.height;
- setTween(myShape, nHeight - radius);
- }
- function setTween(target, bottom) {
- var myTween = new createjs.Tween(target);
- myTween.to({y:bottom, rotation:360}, 5000, createjs.Ease.bounceOut);
- }
|
02-03 TickerクラスでStageオブジェクトを繰返し描き替える
EaselJSでアニメーションを表示するには、ステージ(Stageオブジェクト)が繰返し描き替えられなければならない。そのためには、Tickerクラスの"tick"イベントにリスナー関数を加え、その関数からStage.update()メソッドを呼出す。リスナー関数を加えるメソッドはTicker.addEventListener()で、第1引数にはイベントの"tick"、第2引数にリスナー関数を渡す。
createjs.Ticker.addEventListener("tick", リスナー関数)
初期設定の関数(initialize() )で、Tickerクラスの"tick"イベントにリスナー関数を加えた(第14行目)。リスナー関数(refreshScreen())は、Stage.update()メソッドを呼出している(第22行目)[*1]。
- function initialize() {
- createjs.Ticker.addEventListener("tick", refreshScreen);
- }
- function refreshScreen() {
- stage.update();
- }
|
つぎのコード002は、星形のインスタンスをCanvas上端から回しながら落として弾ませる。
コード002■TweenJSで星形を回しながら落として弾ませる
- <script src="lib/easeljs-0.6.0.min.js"></script>
- <script src="lib/tweenjs-0.4.0.min.js"></script>
- <script>
- var stage;
- var radius = 40;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- var nWidth = canvasElement.width;
- var nHeight = canvasElement.height;
- stage = new createjs.Stage(canvasElement);
- var myShape = createShape(nWidth / 2, -radius);
- setTween(myShape, nHeight - radius);
- stage.addChild(myShape);
- createjs.Ticker.addEventListener("tick", refreshScreen);
- stage.update();
- }
- function setTween(target, bottom) {
- var myTween = new createjs.Tween(target);
- myTween.to({y:bottom, rotation:360}, 5000, createjs.Ease.bounceOut);
- }
- function refreshScreen() {
- stage.update();
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, radius, 5, 0.6, -90);
- }
- </script>
|
[*1] Function.bind()メソッドを使えば、Stage.update()メソッドをリスナーに定められる。
- // createjs.Ticker.addEventListener("tick", refreshScreen);
createjs.Ticker.addEventListener("tick", stage.update.bind(stage));
|
ただし、タイプが楽になるほかは、処理のうえでの利点は感じられない。詳しくは、「EaselJSのイベントリスナーにFunction.bind()メソッドを適用するとリスナー内から削除できない」参照。
また、Ticker.addEventListener()メソッドの第2引数にStageオブジェクトを渡すと、Ticker.tickイベントで内部的にStage.update()メソッドが呼出される。Function.bind()メソッドを使うより、こちらの方がよいだろう。詳しくは、F-site「Ticker.addEventListener()メソッドにStageオブジェクトを渡す」参照。
- // createjs.Ticker.addEventListener("tick", refreshScreen);
createjs.Ticker.addEventListener("tick", stage);
|
|
02-04 トゥイーンに待ちとフェードアウトを加える
TweenオブジェクトにTweenのメソッドで設定を加えれば、それらは順にトゥイーンアニメーションされる。バウンドし終えた後、1秒後にインスタンスをアルファでフェードアウトしてみる(図004)。
図004■バウンドし終えた星が1秒後にフェードアウトする
トゥイーンをしばらく待たせるには、Tween.wait()メソッドを使う。引数には待ち時間をミリ秒で渡す。
Tweenオブジェクト.wait(待ち時間)
回りながら落ちて弾むトゥイーン(第16行目)の後に、1秒間の待ち(第17行目)とアルファのフェードアウト(第18行目)を加えた。
- function setTween(target, bottom) {
- var myTween = new createjs.Tween(target, {loop:true});
- myTween.to({y:bottom, rotation:360}, 5000, createjs.Ease.bounceOut);
- myTween.wait(1000);
- myTween.to({alpha:0}, 2500, createjs.Ease.circIn);
- }
|
さらに、Tween()コンストラクタの第2引数にObjectインスタンスを加え、loopプロパティをtrueに定めた。すると、定めたトゥイーンはずっと繰返される。つぎのコード003は、インスタンスが回りながら落ちてバウンドし、1秒待ってフェードアウトするというトゥイーンを繰返す。
コード003■TweenJSでトゥイーンを組合わせて繰返す
- var stage;
- var radius = 40;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- var nWidth = canvasElement.width;
- var nHeight = canvasElement.height;
- stage = new createjs.Stage(canvasElement);
- var myShape = createShape(nWidth / 2, -radius);
- setTween(myShape, nHeight - radius);
- stage.addChild(myShape);
- createjs.Ticker.addEventListener("tick", refreshScreen);
- stage.update();
- }
- function setTween(target, bottom) {
- var myTween = new createjs.Tween(target, {loop:true});
- myTween.to({y:bottom, rotation:360}, 5000, createjs.Ease.bounceOut);
- myTween.wait(1000);
- myTween.to({alpha:0}, 2500, createjs.Ease.circIn);
- }
- function refreshScreen() {
- stage.update();
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, radius, 5, 0.6, -90);
- }
|
TweenJSのページのデモ「SPARK TABLE」は、Easeクラスのイージング関数による値の変化をグラフで表す。
図005■Easeクラスのイージング関数による値の変化が確かめられる「SPARK TABLE」
03 EaselJSでマウスイベントを扱う
オブジェクトへのマウスクリックと、ドラッグ&ドロップを試してみる。
03-01 オブジェクトをクリックしたら回す
インスタンスへのマウス操作で行いたい処理は、そのインスタンスにEventDispatcher.addEventListener()メソッドでリスナー関数を加える。
オブジェクト.addEventListener(イベント, リスナー関数)
マウスクリックは"click"イベントで捉える(第6行目)。リスナー関数が受取るイベントオブジェクトのMouseEvent.targetプロパティにより、マウス操作されているインスタンスの参照が得られる(第12行目)。したがって、つぎのリスナー関数(rotate())は、クリックしたインスタンスを回転する(図006)。
図006■インスタンスをクリックすると回る
- function initialize() {
- myShape.addEventListener("click", rotate);
- }
- function rotate(eventObject) {
- var instance = eventObject.target;
- instance.rotation += 15;
- stage.update();
- }
|
つぎのコード004は、Canvasの真ん中に置いた星形のShapeインスタンスに"click"イベントのリスナー関数を加え、クリックするたびに回転する。
コード004■オブジェクトをクリックしたら回す
- var stage;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- stage = new createjs.Stage(canvasElement);
- var myShape = createShape(canvasElement.width / 2, canvasElement.height / 2);
- myShape.addEventListener("click", rotate);
- stage.addChild(myShape);
- stage.update();
- }
- function rotate(eventObject) {
- var instance = eventObject.target;
- instance.rotation += 15;
- stage.update();
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
- }
|
03-02 オブジェクトをドラッグ&ドロップする
インスタンスのドラッグ&ドロップは、インスタンス上でマウスボタンを押した"mousedown"イベントで、ドラッグの処理(startDrag())を始める(第6行目)。ドラッグはマウスを動かす"mousemove"イベントにリスナー関数(drag())を定め、マウスポインタの座標にインスタンスの座標を合わせる(図007)。
図007■インスタンスをドラッグ&ドロップする
"mousemove"イベントのリスナー関数は、MouseEventオブジェクトに加える(第13行目)。また、マウスポインタの座標は、リスナーが受取ったMouseEventオブジェクトのプロパティMouseEvent.stageXとMouseEvent.stageYで得られる(第18〜19行目)。
- function initialize() {
- myShape.addEventListener("mousedown", startDrag);
- }
- function startDrag(eventObject) {
- eventObject.addEventListener("mousemove", drag);
- }
- function drag(eventObject) {
- var instance = eventObject.target;
- instance.x = eventObject.stageX;
- instance.y = eventObject.stageY;
- stage.update();
- }
|
リスナー関数を除くには、加えたオブジェクトに対してEventDispatcher.removeEventListener()メソッドを呼出す。
オブジェクト.removeEventListener(イベント, リスナー関数)
マウスボタンを放す"mouseup"イベントで、リスナーを除いて初めの状態に戻す(第14行目)。リスナーを加えたのはMouseEventオブジェクトなので、その参照をドラッグするインスタンスに加えた(第11〜12行目)。
"mouseup"イベントのリスナー関数(stopDrag())は、引数のMouseEventオブジェクトのMouseEvent.targetプロパティからドラッグしているインスタンスの参照を得て(第23行目)、さらにその変数からリスナーを除くMouseEventオブジェクトの参照を取出している(第24行目)。そのMouseEventオブジェクトからEventDispatcher.removeEventListener()メソッドでリスナーを除く(第25〜26行目)。
- function startDrag(eventObject) {
- var instance = eventObject.target;
- instance.dispatcher = eventObject;
- eventObject.addEventListener("mouseup", stopDrag);
- }
- function stopDrag(eventObject) {
- var instance = eventObject.target;
- var dispatcher = instance.dispatcher;
- dispatcher.removeEventListener("mousemove", drag);
- dispatcher.removeEventListener("mouseup", stopDrag);
- }
|
つぎのコード005は、インスタンス上でマウスボタンを押すと、マウスを動かす操作にリスナー関数が加えられて、インスタンスの位置をマウスポインタに追随させる。マウスボタンを放すと、マウスを動かす操作とボタンを放したときのリスナーはともに除かれる。
コード005■オブジェクトをドラッグ&ドロップする
- var stage;
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- stage = new createjs.Stage(canvasElement);
- var myShape = createShape(canvasElement.width / 2, canvasElement.height / 2);
- myShape.addEventListener("mousedown", startDrag);
- stage.addChild(myShape);
- stage.update();
- }
- function startDrag(eventObject) {
- var instance = eventObject.target;
- instance.dispatcher = eventObject;
- eventObject.addEventListener("mousemove", drag);
- eventObject.addEventListener("mouseup", stopDrag);
- }
- function drag(eventObject) {
- var instance = eventObject.target;
- instance.x = eventObject.stageX;
- instance.y = eventObject.stageY;
- stage.update();
- }
- function stopDrag(eventObject) {
- var instance = eventObject.target;
- var dispatcher = instance.dispatcher;
- dispatcher.removeEventListener("mousemove", drag);
- dispatcher.removeEventListener("mouseup", stopDrag);
- }
- function createShape(nX, nY) {
- var myShape = new createjs.Shape();
- myShape.x = nX;
- myShape.y = nY;
- drawStar(myShape.graphics);
- return myShape;
- }
- function drawStar(myGraphics) {
- myGraphics.beginFill("#0000FF");
- myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
- }
|
作成者: 野中文雄
更新日: 2013年2月25日 注[*1]に、Ticker.addEventListener()メソッドの第2引数としてStageオブジェクトを渡す手法追加。
更新日: 2013年2月21日「Stage3D勉強会(第3回) 活動レポート」へのリンクを追加。
作成日: 2013年2月15日