サイトトップ

Director Flash 書籍 業務内容 プロフィール
■Twitter: @FumioNonaka / Facebook Page: CreateJS / Away3D

CreateJS Workshop vol.07

EaselJS 0.8.2の改訂項目とgskinner labの作例「Arc Rainbow」


まず、2015年11月26日にビルドが改められたEaselJS 0.8.2について、改訂されたおもな項目を簡単に紹介する。つぎに、gskinnerチームの習作が公開されているLabから「Arc Rainbow」を採り上げ、その中で用いられているGraphicコマンドなどの技術を解説しよう。


01 EaselJS 0.8.2で改訂されたおもな項目

CreateJS 2015年11月26日付ビルドのライブラリごとの細かな改訂項目は、それぞれに付属するVERSIONS.txtの一覧にもとづいて以下のノートにまとめた。ここではEaselJS 0.8.2のおもな改訂についてご紹介する。

EaselJSライブラリのコンパクト版にMovieClipクラスが含まれた

MovieClipクラスは、EaselJSライブラリのコンパクト(min)版に含まれた(図001)。したがって、MovieClipクラスのコンパクト版は提供されない。

図001■MovieClipクラスはEaselJSライブラリに含まれた

図001

SpriteSheetクラスのイメージの扱いにエラーの処理を追加

SpriteSheetクラスにSpriteSheet.errorイベントが加わり、イメージの扱いにエラーが起きたときの処理を定められるようになった。

SpriteSheetBuilder()コンストラクタの引数でSpriteSheet.framerateプロパティの値が定められる

SpriteSheetBuilderクラスでSpriteSheetオブジェクトをつくるとき、SpriteSheetBuilder()コンストラクタの引数でSpriteSheet.framerateプロパティの値が定められるようになった(デフォルト値は0でTickerクラスの定めにしたがう)。

	
SpriteSheetBuilder(フレームレート)

SpriteSheetBuilder.animations()メソッドがspeedプロパティに対応

また、SpriteSheetBuilder.addAnimation()メソッドの第4引数は、速さのプロパティとしてfrequencyでなくspeedを与えるように改められた。EaselJS 0.7.0でSpriteSheet()コンストラクタに渡すオブジェクトのanimationsプロパティに定める再生の速さのプロパティが、frequencyからspeedに変わったことに合わせた(「EaselJS 0.7.0の改訂」01「重要な変更(旧コンテンツとの互換性を損なう)」参照)。

クラスの内部における配列の判別処理をArray.isArray()メソッドに改訂

クラスSpriteSheetとPreloadJSのLoadQueueの内部処理で、配列かどうかを確かめるのにinstanceof演算子でなくArray.isArray()メソッドが用いられるようになった(「オブジェクトが配列かどうかを確かめる」参照)。

バグの修正


02 gskinner labの作例「Arc Rainbow」

Grant Skinner氏による作例「Arc Rainbow」にもとづき、コードの構造をわかりやすく整えたのがつぎのサンプル001だ。EaselJSのGraphics.commandプロパティを使っている。

サンプル001■CreateJS 15/11/26: Arc Rainbow

Graphicsコマンドでトゥイーンアニメーションを描く

前掲サンプル001の中で円弧のアニメーションのみ抜き出したのが、つぎのサンプル002になる。以下に抜き出したコードのようにGraphics.arc()メソッドは初めに1度しか呼び出されていない。Ticker.addEventListener()メソッドにTicker.tickイベントのリスナーとしてStageオブジェクトを渡しているので、Ticker.tickイベントではStage.update()メソッドが呼び出されるだけだ(「EaselJS 0.8.1: イベントリスナーを扱うEventDispatcher」「説明」参照)。それでも、円弧が描き直されている。

サンプル002■CreateJS 15/11/26: Arc tween animation with Graphics command


function initialize(eventObject) {

	draw();
	stage.update();
	createjs.Ticker.addEventListener("tick", stage);
}
function draw() {

	graphics.setStrokeStyle(10 + Math.random() * 10)
	.beginStroke(color);
	var arcCommand = graphics.arc(0, 0, 50, randomAngle, randomAngle).command;

}

Graphicsコマンドを使わず、円弧は関数(update())で描き変えるとすれば、たとえばつぎのようにTween.changeイベントのリスナーに定めることになる。トゥイーンする円弧を描くためにGraphics.arc()メソッドに渡す引数値はオブジェクト(settings)に定め、それをトゥイーンの対象としてTween.get()メソッドに与えた。これで円弧がトゥイーンアニメーションで描ける。


var settings;

function draw() {

	graphics.setStrokeStyle(thickness)
	.beginStroke(color);
	.arc(0, 0, 50, randomAngle, randomAngle);

	settings = {endAngle: randomAngle, startAngle: randomAngle, color:color, thickness: thickness}
	var tween = createjs.Tween.get(settings, {loop: true})
	.to({endAngle: angle}, Math.random()* angle * 100 + 3000, createjs.Ease.easeOut)
	.to({startAngle: angle}, Math.random() * 1000 + 3000, createjs.Ease.easeIn);
	tween.addEventListener("change", update);

}
function update(eventObject) {

	graphics.clear()
	.setStrokeStyle(settings.thickness)
	.beginStroke(settings.color)
	.arc(0, 0, 50, settings.startAngle, settings.endAngle);
	stage.update();
}

Graphics.commandプロパティから得たGraphicsコマンド(arcCommand)をトゥイーンするなら、上のコードがつぎのように書き替えられる。Tween.get()メソッドには、Graphicsコマンドをトゥイーンの対象として渡した。すると、円弧を書き直すための関数(update())は要らなくなる。

	
// var settings;
function initialize(eventObject) {

	draw();
	stage.update();
	createjs.Ticker.addEventListener("tick", stage);
}
function draw() {

	graphics.setStrokeStyle(thickness)
	.beginStroke(color);
	// .arc(0, 0, 50, randomAngle, randomAngle);
	var arcCommand = graphics.arc(0, 0, 50, randomAngle, randomAngle).command;

	// settings = {endAngle: randomAngle, startAngle: randomAngle, color:color, thickness: thickness}
	// var tween = createjs.Tween.get(settings, {loop: true})
	var tween = createjs.Tween.get(arcCommand, {loop: true})
	.to({endAngle: angle}, Math.random()* angle * 100 + 3000, createjs.Ease.easeOut)
	.to({startAngle: angle}, Math.random() * 1000 + 3000, createjs.Ease.easeIn);
	// tween.addEventListener("change", update);

}
/*
function update(eventObject) {
	var graphics = shape.graphics;
	graphics.clear()
	.setStrokeStyle(settings.thickness)
	.beginStroke(settings.color)
	.arc(0, 0, 50, settings.startAngle, settings.endAngle);
	stage.update();
}
*/

Graphics APIは内部的にGraphicsコマンドを使って描画している(「EaselJS 0.8.0: Graphicsクラス」参照)。その手順はCanvas APIに近い。Graphics.arc()メソッドを呼び出すとGraphics.Arcクラスのコマンドオブジェクトがつくられ、Graphics.commandプロパティから返される。

Graphics.Arcコマンドオブジェクトは円弧の開始角と終了角を、それぞれプロパティGraphics.Arc.startAngleGraphics.Arc.endAngleにもつ。そのため、それらのプロパティはTweenクラスでトゥイーンさせることができ、画面が描き替わるとき(Stage.update()メソッド呼び出し時)に表示は改められる(「Graphicsコマンドでトゥイーンアニメーションを描く」参照)。

DisplayObjectインスタンスにドロップシャドウを加える

DisplayObjectインスタンスのDisplayObject.shadowプロパティShadowオブジェクトを定めると、ドロップシャドウが加わる。ドロップシャドウを消すには、プロパティにnullを与えればよい。Shadow()コンストラクタは、つぎのように4つの引数をとる(デフォルト値は色が黒("black")、あとの3つの引数は0)。


new Shadow (色, 水平のずれ, 垂直のずれ, ぼかし幅)

つぎのコードは、Shapeインスタンス(shape)にドロップシャドウ(shadow)を加える。DisplayObjectインスタンスがひとつでも、影は描画ごとにかかる(図002)。

	
var shape = new createjs.Shape();
var shadow = new createjs.Shadow("#000", 2, 2, 20);
shape.shadow = shadow;

図002■CreateJSとFlash Playerでひとつのオブジェクトにふたつの描画を加えたときの影の違い

  
図002右
>>wonderfl.netへ

Flash Player

オンとオフを切り替える処理

前掲の作例「Arc Rainbow」では、ドロップシャドウのオン・オフを切り替える関数(toggleShadow())はつぎのように定められている(変数名は本稿のサンプルに揃えて変えた。図3参照)。ただ、一見してわかりにくい。これは、関数にブール(論理)値の引数を渡したとき、オン・オフのどちらにするか決められるようにしたためだ。また、条件の評価も、関数を引数なしに呼び出したとき、影をつけるときは3つ、消すときには6つすべて評価しなければならず無駄である。

	
function toggleShadow(show) {
	if (show == true || (show == null && shape.shadow == null)) {
		shape.shadow = shadow;
	} else if (show === false || (show == null && shape.shadow != null)) {
		shape.shadow = null;
	}
}

図003■gskinnerのLabの「Arc Rainbow」が定めている関数

図003

そこでコードを見やすくし、無駄を減らすため、前掲サンプル001ではつぎのふたつの手が加えてある。

  1. 関数の引数がブール値でなければオン・オフの切り替えとする
  2. コード行数は条件(三項)演算子?:を使って減らす

項目1は、ブール値とnull(undefined)以外を無視するかどうかだ。そうしたい場合には、else if条件を加えればよいだろう。項目2は、いずれの場合もプロパティへの代入がともなうので採り入れた。if文を使っても、処理効率は問題ない(「設定のオン・オフを切り替える - トグルボタンの論理組み立て」参照)。コードはつぎのとおりだ。どの場合であっても、ふたつの条件の評価で処理が決まる。


function toggleShadow(show) {
	if (typeof show == "boolean") {
		shape.shadow = show ? shadow : null;
	} else {
		shape.shadow = (shape.shadow == null) ? shadow : null;
	}
}


Appendix Grant Skinner氏からの最新情報

もうすぐ公開されるWebGL向けのクラスSpriteStageでは、SpriteContainerオブジェクトを使わなくてもよくなり、速さや柔軟性が増す。正規リリース1.0も具体的な計画が進んでいる。

作成者: 野中文雄
作成日: 2016年1月23日


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