CAAT::ShapeActor

前々回のtemplateの記事で、ShapeActorクラスを使ったような気がするので、今回はShapeActorを勉強してみました。
CAAT::template - 武田のつぶや日記

CAAT Tutorial 9 - CAAT.Shape object
このwebページを参照しながら、ShapeActorについて学習してみます。

概要

その名前の通り、スクリーン上に形を描くクラスです。
円や四角形を描画する事ができます。
デフォルトでは円を描画する事になっていますが、setShape(shape)メソッドを用いて四角形を描く事もできます。
このメソッドの引数のshapeはCAAT. ShapeActor.prototype.SHAPE_xxxで定義されており、xxxの部分を変更する事によって四角形を描いたりする事が可能となる。
このActorはsetFillStyle( )メソッドをベースに作られています。

サンプル

実際にwebページをもとにsampleを作ってみます。とは言ってもほぼほぼ同じですが。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>samplefile</title>	
	</head>
	<body>
		<script type="text/javascript" src="../../../../build/caat.js"></script>
		<div><canvas id="_c8"></canvas></div>
		<div><span id="_c8_data"></span></div>
		<script type="text/javascript">

			(function( ) {
			 var _director_8 = new CAAT.Director().initialize(
				 1000,
				 300,
				 document.getElementById('_c8')).
			 setClear(false);

			 var _scene_8 = _director_8.createScene();

			 var colors= [ 'blue', 'red', 'yellow', 'white', 'gray' ,'orange' ];
			 var color_index=0;

			 // create a container, equals in size to the director.
			 var root = new CAAT.ActorContainer().
			 create().
			 setBounds(0, 0,
				 _director_8.canvas.width, _director_8.canvas.height).
			 setFillStyle('#000000')
			 root.mouseEnter = function(mouseEvent) {
			 };
			 root.mouseExit = function(mouseEvent) {
			 };

			 _scene_8.addChild(root);

			 // on mouse move over the root Actor
			 root.mouseDrag = function(mouseEvent) {

				 var r = 5 + 15 * Math.random();

				 var bubble;

				 // is pressing control, add a Rectangle-Shaped blue Actor
				 if ( Math.random()<.5 ) {
					 bubble = new CAAT.ShapeActor().
						 setLocation(mouseEvent.point.x, mouseEvent.point.y).
						 setSize(r, r).
						 setShape(CAAT.ShapeActor.prototype.SHAPE_RECTANGLE).
						 enableEvents(false).
						 setCompositeOp('lighter').
						 setFillStyle( colors[(color_index++)%colors.length] );

				 } else {
					 // else, add a Circle-Shaped red Actor
					 bubble = new CAAT.ShapeActor().
						 setLocation(mouseEvent.point.x, mouseEvent.point.y).
						 setSize(r, r).
						 enableEvents(false).
						 setCompositeOp('lighter').
						 setFillStyle( colors[(color_index++)%colors.length] );
				 }

				 root.addChild(bubble);

				 // Add a container behavior, to hold a fading behavior and a moving
				 // behavior.
				 var cb = new CAAT.ContainerBehavior().
					 setFrameTime(_scene_8.time + 2000 + 1000 * Math.random(), 500).
					 addListener(
							 // when the container behavior is expired, expire and discard
							 // the actor.
							 {
								behaviorExpired : function(behaviour, time, actor) {
								actor.
								setDiscardable(true).
								setExpired(true);
								}
							});

// fade from opacity to total transparency
var ab = new CAAT.AlphaBehavior().
setFrameTime(0, 500).
setValues(1, 0);

cb.addBehavior(ab);

// follow a vertical path of at least 100 pixels
var tb = new CAAT.PathBehavior().
setFrameTime(0, 500).
setPath(
		new CAAT.Path().setLinear(
			bubble.x, bubble.y,
			bubble.x, bubble.y - 100 - 100 * Math.random()));
cb.addBehavior(tb);

bubble.addBehavior(cb);
};

var span = document.getElementById('_c8_data');

_scene_8.onRenderEnd= function() {
	span.innerText= 'Actors: '+root.getNumChildren();
};

CAAT.loop(20);
})( );

</script>
</body>
</html>

CAATのサンプルではマウスを動かすだけで四角や円が描画されていましたが、このままだとどうかと思ったので、ドラッグしたときのみ描画されるようにしてみました。
その様子がこちらです。

実際にドラッグしてるかどうかわかりづらいところですが。

error

最初にspan idタグでidを指定しなかったばかりに実行の度に"cannot set property 'innerText' of null"とエラーメッセージが表示され、色々調べてしまいました。
このエラーメッセージは「htmlファイルを読み込む前にjsファイルが読み込まれてしまっているよ」というような感じらしいですが、単純に_c8_dataというidを指定していなかっただけでした。確かにこのidどこで定義しているんだろうという感じでしたが。

これを解決する際に色々調べてみましたが、innerTextはIEのみでしか動かないといくつかの記事で書いてありましたが、googlechromeでも動いているという事はもう普通に対応されているという事なのでしょうか。

id指定をして問題を解決するために色々試してみたのですが、最初はgetNumChildren( )メソッドが動いていないのかと思い、適当な変数にgetNumChildren( )でとってきた値をConsole.logでコンソールに表示してみたところ、オブジェクトが生成されるたびにきちんと値が変わっていました。
こんな風にしてどこが動いているのかチェックしていくのか、と経験の浅い自分は思ったりしたのですが、とにかくgetNumChildren( )は動いていました。

innerTextがおかしいのかと思い、innerHTMLとかに変えたりもしましたがダメ。
なら、textActorを生成して、このtextをgetNumChildren( )でとってきた値を使って変えてやればいいんじゃね?という事でそれも試してみたり色々しました。
繰り返しになりますが結局idを指定していなかったので何をしてもダメでしたが、setTextはonRenderEnd内では使えないのかな?
ちょっとためしきれていないのですが。。

最終的にはwebページのソースコードを読んでspan idが必要な事に気づきました。

コードリーディング

今回は最初のfunctionから見て行きましょう。ここからはじまるので。
まずdirectorクラスを用いて、横幅1000px、縦幅300pxで初期化し、_c8 idのところに埋め込みます。
setClear( )は透明にするかどうかのメソッドだと思うのですが、trueもfalseも違いがあまりわかりませんでした。
caat.jsファイルを見たりもしましたが。

次にSceneオブジェクトを作成しています。このあたりはテンプレート通りの書き方ですね。

そして描画される図形の色を決めて、index変数を0で初期化しています。これを何に使うかはもう少し先を読んでみるとわかります。


続いてActorContainerオブジェクトが作られています。
今回のような「振る舞い」をもったActorを作成する場合は、その振る舞いを管理するためのオブジェクトとしてActorContainerオブジェクトを作成する必要がある、という認識でよいのかな?
兎にも角にもActorContainerオブジェクトを作成し、今回はこのオブジェクト内にマウスが入った際もマウスが出ていった際も特に何もしないので、mouseEnterもmouseExitも特に定義していません。
そしてこのActorContainerオブジェクトをSceneに追加します。

次にmouseDragの関数を作っていきます。
今回はドラッグした際に描画されるようにしたいのでここに色々書いていきます。
まず、描画される図形の大きさを5〜20として、ShapeActorオブジェクトを入れるbubble変数を定義します。
ランダムに生成した数が0.5より小さいなら四角形、それ以上なら円を描画するようにしています。

上記で紹介したshapeという引数のxxxの部分をSHAPE_RECTANGLEとして四角形にしています。デフォルトでは円ですが、SHAPE_CIRCLEで円になるようです。というかこの二つしかないみたいです。
そして、それぞれ作成したオブジェクトにイベントをつけないので、enableEvents(false)としています。
setCompositeOpはcaat.jsファイルを見てもあまりわかりませんでしたが、合成法につていてのメソッドなのではないかと思います。
そしてFillStyleでcolorIndexを使っています。つまり青、赤、黄、、、と順番に色を出しています。

その後ContainerBehavior( )クラスで振る舞いを決定しています。
setFrameTimeで設定しているののは振る舞いを開始する時間とそのオブジェクトの存在できる時間?
addListenerでイベントリスナーを設定し(この引数がなんなのかいまいちわからなかったので今回は割愛)ます。

そしてAlpheBahavior( )で透過度の設定、この場合500msでvalueを1から0に、つまり透明度0から100に設定し、PassBehaviorでどのように動くのかを設定しています。

最後にinnerTextで_c8_date idのついたところにオブジェクト数の情報を記載できるようにしています。




この後サンプルのコードリーディングをしてみようと思いましたが、なかなかに骨が折れそうだったので、順当にチュートリアルを消化していくことにします。