読了: 約 15 分

今更ながらToolkit for CreateJSでしょっぱいアニメーションを作成しているのでjsとして吐き出す所までをメモしておきます。
10分位で出来るので是非試してみてはいかがでしょうか。

Toolkit for CreateJS導入編

公式サイト

簡単な資料ですが、デザイナーの方でも使えるようになるよねというワークフロー等。

Flashのアニメーションでまず作成

action script3とか使ってクリックしてソーシャルゲームのカードのキラキラみたいなものを作りたいときのものです。
タイムラインでこんな感じに作ります。
※同一レイヤーにはシンボルは一つしかおけないので注意が必要。
遊びでやったのでレイヤーは適当ですが後々jsで吐き出される際にレイヤー1とかになるのでちゃんとした名前を付けておいた方がjsを書く時困りません。
タイムライン3

※実際プログラムはほぼ書いていませんが、ボタンクリックやクリックした時のフレーム移動等やりたい場合は簡単なプログラムが必要になります。

Toolkit for createJSでjsに吐き出し

[ウィンドウ]->[Toolkit for CreateJS]
js,html,image(フォルダ)という感じで指定したフォルダに吐き出されます。
エラーをはいている場合jsに途中までの記述がされます。

パブリッシュ

パブリッシュ2

少し不便なのが、flash上のパネルの[出力]の欄にエラーが出た場合警告が表示されますが、そこではどこのレイヤーで問題が起きているかというのが表示されない?ので上記のようにJSからのデバックしています。もっと良い方法があると思いますが。

パブリッシュの際のエラーへの対処法

警告 :
テキスト関連機能のサポートは制限されています。通常は、テキストを HTML エレメントとして含めることを推奨します (DOMElement を参照)。
クラシックトゥイーンを含むレイヤー上には、シンボルインスタンスを 1 つしか配置できません。 (2)
EaselJS のフレーム番号は 1 ではなく 0 から始まっています。これは gotoAndStop や gotoAndPlay などのメソッドの呼び出しに影響します。 (2)
テキスト入力および静止テキストのテキストフィールドはダイナミックテキストとしてパブリッシュされます。

・クラシックトゥイーンを含むレイヤーは下記のように二つに分けて処理をする必要があります。
タイムライン

・テキスト関連~
こちらはflashでテキスト機能を使っているので、これは表示されないのでhtml側で入れてくださいというそのままですが。

・EaselJSの場合フレーム番号が異なる
これは下記のように通常タイムラインは1から始まっていてその通りに機能を作ってしまった場合gotoAndPlay等でフレームを厳密に選択している場合ずれる可能性があるので注意してくださいというものです。
タイムライン2

Toolkit for createJSでの注意点

androidでの挙動

上記したToolkit for createJSで作成したJSですが、androidをサポートしているよという事が売りだったりもするのでChoromeでしか確認していないのでandroidでどうなっているかと思ったので幾つか参考リンクをどうぞ。

CreateJS × Android でハマったこと

といいつつもandroid2.3~とかで試してみましたが余裕で見えますね。
簡単で非常に便利!

書き出されたコード


(function (lib, img, cjs) {

var p; // shortcut to reference prototypes

// stage content:
(lib.create_anime = function(mode,startPosition,loop) {
	this.initialize(mode,startPosition,loop,{},true);

	// レイヤー 8
	this.instance = new lib.hoshi_1();
	this.instance.setTransform(158,29.5,1,1,0,0,0,0,0.5);

	this.instance_1 = new lib.hoshi_1();
	this.instance_1.setTransform(67,150.5,1,1,0,0,0,0,0.5);

	this.instance_2 = new lib.hoshi_1();
	this.instance_2.setTransform(201.1,99.5,0.639,0.639,30,0,0,0.1,0.4);

	this.instance_3 = new lib.hoshi_1();
	this.instance_3.setTransform(135,177.9,0.538,0.538,0,0,0,0,0.5);

	this.instance_4 = new lib.hoshi_1();
	this.instance_4.setTransform(50,69.1,1,1,0,0,0,0,0.5);

	this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.instance_4},{t:this.instance_3},{t:this.instance_2},{t:this.instance_1},{t:this.instance}]},86).wait(19));

	// レイヤー 7
	this.instance_5 = new lib.hoshi_1();
	this.instance_5.setTransform(158,30.5,1,1,0,0,0,0,0.5);

	this.instance_6 = new lib.hoshi_1();
	this.instance_6.setTransform(67,151.5,1,1,0,0,0,0,0.5);

	this.instance_7 = new lib.hoshi_1();
	this.instance_7.setTransform(201.1,100.5,0.639,0.639,30,0,0,0.1,0.4);

	this.instance_8 = new lib.hoshi_1();
	this.instance_8.setTransform(135,178.9,0.538,0.538,0,0,0,0,0.5);

	this.instance_9 = new lib.hoshi_1();
	this.instance_9.setTransform(50,70.1,1,1,0,0,0,0,0.5);

	this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.instance_9},{t:this.instance_8},{t:this.instance_7},{t:this.instance_6},{t:this.instance_5}]},82).to({state:[]},5).wait(18));

	// レイヤー 2
	this.instance_10 = new lib.hoshi_1();
	this.instance_10.setTransform(159,30.5,1,1,0,0,0,0,0.5);

	this.instance_11 = new lib.hoshi_1();
	this.instance_11.setTransform(68,151.5,1,1,0,0,0,0,0.5);

	this.instance_12 = new lib.hoshi_1();
	this.instance_12.setTransform(202.1,100.5,0.639,0.639,30,0,0,0.1,0.4);

	this.instance_13 = new lib.hoshi_1();
	this.instance_13.setTransform(136,178.9,0.538,0.538,0,0,0,0,0.5);

	this.instance_14 = new lib.hoshi_1();
	this.instance_14.setTransform(51,70.1,1,1,0,0,0,0,0.5);

	this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.instance_14},{t:this.instance_13},{t:this.instance_12},{t:this.instance_11},{t:this.instance_10}]},78).to({state:[]},5).wait(22));

	// レイヤー 6
	this.instance_15 = new lib.daikiji();
	this.instance_15.setTransform(153.5,136.1,1.823,1.944,0,0,0,84.2,70);
	this.instance_15._off = true;

	this.timeline.addTween(cjs.Tween.get(this.instance_15).wait(74).to({_off:false},0).to({_off:true},30).wait(1));

	// omikujibou
	this.instance_16 = new lib.omikujibou_1();
	this.instance_16.setTransform(218.1,88.1,0.481,0.481,0,0,0,60.1,-85.9);
	this.instance_16._off = true;

	this.timeline.addTween(cjs.Tween.get(this.instance_16).wait(44).to({_off:false},0).to({x:278.1,y:8.7,alpha:0},30).to({_off:true},1).wait(30));

	// レイヤー 11
	this.omikujiBtn_mv = new lib.omikujiBtn();
	this.omikujiBtn_mv.setTransform(153,199.4,1,1,0,0,0,83,20.5);
	this.omikujiBtn_mv._off = true;

	this.timeline.addTween(cjs.Tween.get(this.omikujiBtn_mv).wait(44).to({_off:false},0).to({alpha:0},30).to({_off:true},1).wait(30));

	// レイヤー 4
	this.omikujiBtn_mv_1 = new lib.omikujiBtn();
	this.omikujiBtn_mv_1.setTransform(152,204.4,1,1,0,0,0,83,20.5);

	this.timeline.addTween(cjs.Tween.get(this.omikujiBtn_mv_1).to({_off:true},44).wait(61));

	// レイヤー 9
	this.instance_17 = new lib.haikei();
	this.instance_17.setTransform(153.5,136,1,1,0,0,0,153.5,136);
	this.instance_17._off = true;

	this.timeline.addTween(cjs.Tween.get(this.instance_17).wait(44).to({_off:false},0).to({alpha:0},30).to({_off:true},1).wait(30));

	// レイヤー 3
	this.instance_18 = new lib.haikei();
	this.instance_18.setTransform(153.5,136,1,1,0,0,0,153.5,136);

	this.timeline.addTween(cjs.Tween.get(this.instance_18).to({_off:true},44).wait(61));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(119.4,40.5,307,272);


// symbols:
(lib.hoshi = function() {
	this.initialize(img.hoshi);
}).prototype = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,53,52);


(lib.omikuji = function() {
	this.initialize(img.omikuji);
}).prototype = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,103,98);


(lib.omikuji2 = function() {
	this.initialize(img.omikuji2);
}).prototype = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,166,41);


(lib.omikujibou = function() {
	this.initialize(img.omikujibou);
}).prototype = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,44,74);


(lib.stage = function() {
	this.initialize(img.stage);
}).prototype = new cjs.Bitmap();
p.nominalBounds = new cjs.Rectangle(0,0,307,272);


(lib.tween2 = function() {
	this.initialize();

	// レイヤー 1
	this.instance = new lib.omikujibou();
	this.instance.setTransform(-11.6,-41.4,1,1,15);

	this.addChild(this.instance);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-30.7,-41.4,61.7,82.9);


(lib.omikujiBtn = function() {
	this.initialize();

	// レイヤー 1
	this.instance_1 = new lib.omikuji2();

	this.addChild(this.instance_1);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,166,41);


(lib.omikuji_1 = function() {
	this.initialize();

	// レイヤー 1
	this.instance_2 = new lib.stage();

	this.addChild(this.instance_2);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,307,272);


(lib.hoshi_1 = function() {
	this.initialize();

	// レイヤー 1
	this.instance_3 = new lib.hoshi();
	this.instance_3.setTransform(-26.4,-25.5);

	this.addChild(this.instance_3);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-26.4,-25.5,53,52);


(lib.daikiji = function() {
	this.initialize();

	// レイヤー 1
	this.text = new cjs.Text("大吉", "20px Apple LiGothic", "#FFFFFF");
	this.text.lineHeight = 22;
	this.text.setTransform(60,60.5);

	this.shape = new cjs.Shape();
	this.shape.graphics.f("#CC0000").s().p("ANKK7I6TAAIAA11IaTAAIAAV1").cp();
	this.shape.setTransform(84.2,70);

	this.addChild(this.shape,this.text);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,168.5,139.9);


(lib.omikujibou_1 = function() {
	this.initialize();

	// レイヤー 1
	this.instance_4 = new lib.tween2("synched",0);
	this.instance_4.setTransform(60.1,-85.9);

	this.addChild(this.instance_4);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(29.3,-127.4,61.7,82.9);


(lib.haikei = function() {
	this.initialize();

	// レイヤー 1
	this.image = new lib.omikuji_1();
	this.image.setTransform(153.5,136,1,1,0,0,0,153.5,136);

	this.addChild(this.image);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,307,272);

})(lib = lib||{}, images = images||{}, createjs = createjs||{});
var lib, images, createjs;




var canvas, stage, exportRoot;

function init() {
	canvas = document.getElementById("canvas");
	images = images||{};

	var manifest = [
		{src:"<%= image_path('campaign/hoshi.png')%>", id:"hoshi"},
		{src:"<%= image_path('campaign/omikuji.png')%>", id:"omikuji"},
		{src:"<%= image_path('campaign/omikuji2.png')%>", id:"omikuji2"},
		{src:"<%= image_path('campaign/omikujibou.png')%>", id:"omikujibou"},
		{src:"<%= image_path('campaign/stage.jpg')%>", id:"stage"}
	];

	var loader = new createjs.PreloadJS(false);
	loader.onFileLoad = handleFileLoad;
	loader.onComplete = handleComplete;
	loader.loadManifest(manifest);
}

function handleFileLoad(o) {
	if (o.type == "image") { images[o.id] = o.result; }
}

function handleComplete() {
	exportRoot = new lib.create_anime();

	stage = new createjs.Stage(canvas);
	stage.addChild(exportRoot);
	stage.update();

	createjs.Ticker.setFPS(24);
	createjs.Ticker.addListener(stage);
}

一部プロジェクトで使っているrubyのimage_pathという書き方をしている箇所がありますが、
image/~.pngとかで大丈夫です。

まとめ

  • Flaファイルがあれば結構楽に変更出来る
  • 最初から640*960とかでステージ作っておく
  • androidでも通常営業
  • デザイナーがアニメーションを作る際の神のようなツール
  • パブリッシュの際のデバックが少し面倒