POPSブログ

CreateJS MotionGuidePlugin 利用して、テキストアニメーションを作る一例です

240

  Category:  javascript2013/08/08 pops 

CreateJS MotionGuidePlugin による「テキストアニメーション」のシミュレーションで取得した「パスデータ」を実際に組み込んだ例です。判り易いように簡単に作ります。
easeljs-0.7 でのテストです。

 

CreateJS MotionGuidePlugin 利用して、テキストアニメーションを作る一例


2013/09/25/EaselJSなどバージョンUPされました(easeljs-0.7)。動作など確認してeaseljs-0.7用に更新しています。(2013/10/22)


原則、前頁掲載のシミュレーションで「パスデータ」を取得した場合の組み込みの例です。勿論パスが単純なら手書きでも可能です。
シミュレーションのページにも簡単に説明してはいますが、多少わかり難いと思いますので、取得「パスデータ」を使用した、簡単なテキストアニメーションの例を掲載します。


[説明図]

 

1. パスは標準のパスの最終ポイントをずらしただけの簡単なものです。(x=500,y=-150)
2. 通常は各ポイントに文字位置情報を加算して右にずらしています。(切り替え可能な仕組みにします)
3. 今回は最終ポイントを固定して、最終ポイントから文字を吹き出させ、戻りはその位置に戻す、このような感じにします。(文字の数、固定点の違いなどで変化はあります)
4. 最終ポイントに文字位置情報を加算していないだけです。パスの形は途中変わりますがそれなりの効果がでます。(MotionGuide利用は作業効率が良い)
5. 設定などはJS上部をご覧下さい。


DEMO


CreateJS MotionGuidePlugin 利用のテキストアニメーションの例 (createJS030.js)

このページはHTML5では有りませんので、デモページでご覧ください。「IE7.8」ではご覧いただけません。
/// 注意、ブラウザ、マシン性能により描画品質などに大きな差が有ります事了承下さい ///


Chrome Firefox Safari(Win) IE9、で動作確認済み。 (Safari(Mac)、IE10は未確認です)


 

HTML JS CSS


使用するライブラリ

easeljs preloadjs tweenjs

配布元 : CreateJS createjs.com


ライブラリの読み込み

ダウンロードしたJSを使用する場合。記述は一例です。(バージョン 0.7.0 使用)


<script type="text/javascript" src="js/easeljs-0.7.0.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.0.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。このデモでは preloadjs を使用していません。


HTML (HTML5)


<div id="demo-wrap">
	<div id="image-box" class="radius"><canvas id="mainCanvas" width="640" height="300"></canvas></div>
</div>

JS

createJS030.js、JS名は任意に変更可。説明用のため極単純にしています。easeljs-0.7用


//日本語
//createJS030.js
//easeljs-0.7用MotionGuideアニメーション
//rainbow-Color

//------------------------------------------------------

//ガイド設定
//ガイド幅、標準 canvasWidth
var guide_w=500;
//ガイド高さ、標準0
var guide_h=-150;

//ポイント固定 true false
var movePoint=true;

//間隔の基準時間//100-250
var base_time=200;
//交互遅延時間 500-1000
var delayed_time=1000;

//メインテキスト
var mainstring="ViVa POPS WEB KOUBOU";

//canvasの大きさ/全てこの値を使用
var canvasWidth=640;
var canvasHeight=300;

//------------------------------------------------------

//Plugin読み込み
createjs.MotionGuidePlugin.install();

//変数、未使用もあり
//ステージ
var stage;
//コンテナなど
var backrect;
var welcomecontainer;
var welcomeImage;
//TEXT
var viewtext;

//MAIN-TEXT
var maintextcontainer;
var maintext;
//MOVE-TEXT
var textChip=[];
//並び順のポジション保存
var textPosx=[];
var textPosy=[];
//MOVEポジション保存
var movePosx=[];
var movePosy=[];

//------------------------------------------------------
//shadowフィルター
var shadow=new createjs.Shadow("#000000",0,0,4);
var shadow2=new createjs.Shadow("#FFFFFF",0,0,6);//影2

var backchg_no=0;
var backcolors=["#000000","#FFFFFF","#778899","#BC8F8F","#20B2AA"];//背景色

//テキスト用グローバル変数
var textmax=0;
var textcount=0;

//------------------------------------------------------

//ステージ周りセット
function init() {

	//STAGE
	stage=new createjs.Stage('mainCanvas');

	//バックRect/最下位色背景層、無くとも良い
	backrect=new createjs.Shape();
	backrect.graphics.beginFill("#000000").drawRect(0,0,canvasWidth,canvasHeight);

	//クリック
	backrect.addEventListener("click",backchg);
	stage.addChild(backrect);

	//MAIN-TEXT
	maintextcontainer=new createjs.Container();
	//位置中央/あとで修正される
	maintextcontainer.x=canvasWidth/2;
	maintextcontainer.y=canvasHeight/2;
	stage.addChild(maintextcontainer);

	//簡易TEXT、Arialに変更
	viewtext=new createjs.Text("","12px Arial","#FFFFFF");
	viewtext.x=20;
	viewtext.y=15;
	viewtext.maxWidth=canvasWidth-40;
	viewtext.lineHeight=20;
	viewtext.textBaseline="bottom";
	viewtext.shadow=shadow;//SHADOW処理
	stage.addChild(viewtext);
	set_text("START");

	stage.update();

	createjs.Ticker.setFPS(30);
	createjs.Ticker.addEventListener('tick',tick);

	//調整
	setTimeout(function() {

		//プロローグ表示に進む
		set_prologue();

	},2000);

}

//プロローグ
function set_prologue() {

	set_text("START");

	//調整
	setTimeout(function() {

		//MAIN-TEXT
		set_mainanime();

	},2000);

}

//MAINテキストアニメ
function set_mainanime() {

	set_text("ANIMATION");

	textcount=0;//カウント、グローバル

	textChip=[];//クリア
	//MAINテキストアニメーション
	var maintext_W=0;
	var text_spc=0;//テキストスペース
	var center=true;

	//インスタンス配列取得
	//サイズ,フォント,色,虹色,スペース,文字
	textChip=createMoveText("40px","Arial","#FFFFFF",true,text_spc,mainstring);
	var textlen=mainstring.length;
	//テキスト用グローバル変数
	textmax=textlen;

	//全幅の計算を先に計算
	for (var i=0; i < textlen; i++) {
		maintext_W +=textChip[i].width;
		if(i < textlen) {maintext_W +=text_spc;}
	}
	//コンテナ中央補正
	if (center) {maintextcontainer.x=(canvasWidth-maintext_W)/2;}

	//遅延保存
	var delay_st=[];

	//多目的判定用フラグ/未使用もあり
	var chgxyflag=Math.floor(Math.random()*5);
	//多目的用2
	var chgflag=Math.floor(Math.random()*3);
	var chgflag2=Math.floor(Math.random()*3);
	var chgflag3=Math.floor(Math.random()*3);//ガイド用
	//逆転フラグ
	var chg_v=Math.floor(Math.random()*2);
	if (chg_v < 1) {chg_v=-1;}

	//delay番号/現在未使用
	var delay_no=Math.floor(Math.random()*4);

	var sh=textlen-1;
	var k=0;
	var flag=-1;

	for (var i=0; i < textlen; i++) {

		//ID
		textChip[i].id=i;
		//addChild
		maintextcontainer.addChild(textChip[i]);

		//ポジション取得
		textPosx[i]=textChip[i].x;
		textPosy[i]=textChip[i].y;

		//ポイント固定
		if (movePoint) {
			textChip[i].x=guide_w;
			textChip[i].y=guide_h;
		}
		//X方向ポイント移動
		if (!movePoint) {
			textChip[i].x=guide_w+textPosx[i];
			textChip[i].y=guide_h;
		}

		//MOVEポジション保存
		movePosx[i]=textChip[i].x;
		movePosy[i]=textChip[i].y;

		//セット
		textChip[i].rotation=360;
		textChip[i].alpha=1;
		textChip[i].scaleX=0.1;
		textChip[i].scaleY=0.1;

		//delay計算/現在文字列順
		delay_st[i]=base_time*i;

		/*
		if (delay_no == 0) {delay_st[i]=base_time*(sh-i);}//逆順
		if (delay_no == 1) {delay_st[i]=Math.abs(i-sh/2)*base_time;}//中から
		if (delay_no == 2) {delay_st[i]=Math.abs(Math.abs(i-sh/2)-textlen/2)*base_time;}//外から
		*/

		//交互遅延
		if (chgflag2 == 1) {
			if (flag == 1) {delay_st[i] +=delayed_time;}
		}

		k ++;
		flag *=-1;
	}

	//delayの最大値を求める
	var max_delay=Math.max.apply(null,delay_st);

	var flag=-1;
	//Tween
	for (var i=0; i < textlen; i++) {

		//Tween
		var twn=createjs.Tween.get(textChip[i]);
		twn.wait(delay_st[i])
		.to({guide:{path:[textPosx[i],textPosy[i], 100+textPosx[i],-150,200+textPosx[i],0, 300+textPosx[i],150,movePosx[i],movePosy[i]],orient:false,start:1,end:0},rotation:0,scaleX:1,scaleY:1,alpha:1},2000)//右用
		.to({x:textPosx[i],y:textPosy[i],rotation:0},50);

		twn.wait(50).to({x:textPosx[i],y:textPosy[i]},50)
		.wait(100).to({scaleX:2,scaleY:2},50)
		.wait(100).to({scaleX:1,scaleY:1},200);

		if (chgflag == 0) {
			twn.wait(1000).to({y:-30*flag},400)
			.to({y:textPosy[i]},100);
		}

		twn.call(finshmove)//shadow
		.wait(max_delay-delay_st[i])//最大値利用時間差吸収
		.wait(1000)
		.to({rotation:360*chg_v},1000)
		.to({rotation:0},1)
		.wait(8000)
		.wait(delay_st[i])
		.call(finshmove2)//shadow-clear
		.wait(500)
		.to({guide:{path:[textPosx[i],textPosy[i], 100+textPosx[i],-150,200+textPosx[i],0, 300+textPosx[i],150,movePosx[i],movePosy[i]],orient:false,start:0,end:1},scaleX:0.1,scaleY:0.1,alpha:1,rotation:360},2000)
		.call(function(){
			//終了
			if (textcount == textmax-1) {finshtextAll();}
			textcount +=1;//グローバルの事
		});

		flag *=-1;
	}

}

//テキストshadow
function finshmove() {
	this.shadow=shadow2;
}
function finshmove2() {
	this.shadow=null;
}

//MAINテキスト終了
function finshtextAll () {
	reset_parts();
}

//reset_parts
function reset_parts() {

	set_text("CLEAR");

	//MAIN-TEXTコンテナの中を削除
	maintextcontainer.removeAllChildren();

	stage.update();
	//調整
	setTimeout(function() {
		set_prologue();
	},2000);

}

//tickステージ
function tick() {
	stage.update();
}

//背景色変更
function backchg() {
	backchg_no ++;
	if (backchg_no > backcolors.length-1) {backchg_no=0;}
	var color=backcolors[backchg_no];
	backrect.graphics.beginFill(color).drawRect(0,0,canvasWidth,canvasHeight);
}

//MOVEテキストインスタンスを作る
function createMoveText(size,font,color,rainbow,space,str) {

	var fontdata=size + " " + font;

	var chip=[];
	var len=str.length;
	var tpos_x=0;
	var tpos_y=0;

	for (var i=0; i < len; i++) {

		//文字インスタンスを作る
		var t=new createjs.Text("",fontdata,color);
		//1文字入れる
		t.text=str.charAt(i);
		//幅高さ
		var w=t.getMeasuredWidth();
		var h=t.getMeasuredHeight();
		//原点中央
		t.regX=w/2;
		t.regY=h/2;
		//虹色
		if (rainbow) {
			t.color=rainbowColor(i,len,80,40);//rainbow
			//t.color=createjs.Graphics.getHSL(i/len*360,100,50);//直接
		}
		//位置
		tpos_x +=w/2;//half
		t.x=tpos_x;
		t.y=tpos_y;//0
		//位置加算
		tpos_x +=(w/2+space);//half+space
		//大きさ重要
		t.width=w;
		t.height=h;
		//
		chip[i]=t;
	}
	//戻り配列
	return chip;
}

//rainbow-Color
var rainbowColor=function(v,cv,saturation,lightness) {
	var no=v/cv*360;
	var color=createjs.Graphics.getHSL(no,saturation,lightness);
	return color;
}

//VIEWTEXT
function set_text(t) {
	viewtext.text=t;
}

//START
init();

注釈文を削除すれば、幾分早くなります。


CSS

createJS030.css、CSS名は任意に変更可


/*日本語 createJS030.css*/

#demo-wrap {
position:relative;
width:auto;
height:320px;
text-align:center;
}

#image-box {
/*position:absolute;*/
position:relative;
top:0;left:0;
width:640px;
height:300px;
padding:0;
margin:0 auto;
box-shadow:0 0 10px #000;
-moz-box-shadow:0 0 10px #000;
-webkit-box-shadow:0 0 10px #000;
-o-box-shadow:0 0 10px #000;
-ms-box-shadow:0 0 10px #000;
background-color:#000000;
}

#image-box #mainCanvas {
border-radius:10px;
}

.radius {
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
-o-box-border-radius:10px;
-ms-border-radius:10px;
}

当方のサンプルの例です。


簡単な説明


[説明図]


 

1. パスは標準のパスの最終ポイントをずらしただけの簡単なものです(x=500,y=-150)。2次ベジェ曲線ですから、それなりの動きになります。固定の場合はパス波形が変わります。
2. アニメする場合の速度などの条件で、雰囲気が変わりますので適度に調整します。
3. パス情報を書き込み、文字位置の情報を加算するだけです。基本的にY方向は0に成りますので、修正はX方向だけに成ります。
4. 最終ポイントを固定する場合のみ最後の位置を、最終ポイント位置(x=500,y=-150)にします。
5. アニメは IN OUT がありますが、同じパスデータにして、start end で再利用しています。
                                                        


デモは、下の「パスDATA」に基づきますが、書き換えなどは以下の順序で行います。


パスDATAを得る

次ぎのようなデータを得ることが出来ます。


パスDATA
path:[0,0, 100,-150,200,0, 300,150,500,-150]
移動距離 guide_w 値
500

JS先頭の設定に最終ポイント情報を記載する

簡単にするために、最終ポイント情報を記載します。固定しない場合の標準はキャンバス横幅です。500を入力しますが多少変更はかまいません。
ガイド高さ(guide_h)は最終ポイントY位置の-150です。これも多少変更しても構いません。ポイント固定は true にします。false は移動します。


//ガイド幅、標準 canvasWidth
var guide_w=500;
//ガイド高さ、標準0
var guide_h=-150;

//ポイント固定 true false
var movePoint=true;

Tweenのパスデータの変更

[説明図]


当方の文字インスタンス(1文字)はそれぞれ「基準点」から離れた距離(x値が違う、y値は常に0)に有ります。文字位置とガイドの関係には図の様に「ズレ」があるので修正して合わせねば成りません(修正しないと全て基準点に向かいます)。またガイド start end の設定で動く方向を指定することが出来ます。


パスデータに文字のX位置情報が加算されただけです。X軸、Y軸の反転は行っていません。判り易いように簡略化。
IN OUTは、start:1,end:0、start:0,end:1 の違いで、パスデータは同じです。


文字位置情報(原点からの距離)は、textPosx[i] textPosy[i]、に格納されていますので、その値で修正します。ガイドパスを文字の原点にあわせると共にパスの形状も同じにする作業です。(y値は現在0です)
移動した位置情報は、movePosx[i] movePosy[i]、に格納されています。IN の場合のスタート地点の情報になります。



path:[0,0, 100,-150,200,0, 300,150,500,-150]の数値で補正すると以下のようになる

------------------------------------------------------------------------------

IN
.to({guide:{path:[textPosx[i],textPosy[i], 100+textPosx[i],-150,200+textPosx[i],0, 300+textPosx[i],150,movePosx[i],movePosy[i]],orient:false,start:1,end:0},rotation:0,scaleX:1,scaleY:1,alpha:1},2000)//右用

OUT
.to({guide:{path:[textPosx[i],textPosy[i], 100+textPosx[i],-150,200+textPosx[i],0, 300+textPosx[i],150,movePosx[i],movePosy[i]],orient:false,start:0,end:1},scaleX:0.1,scaleY:0.1,alpha:1,rotation:360},2000)

CreateJS MotionGuide クラスについては、以下に少し説明してあります。

【参照】当方の記事: CreateJS 図形テキストをアニメーション、Tween 連続操作と MotionGuideTween の組み合わせ


固定と移動の処理

JS先頭での入力データを下に、以下の所で変更出来るようにしています。但し出現位置は右側のみで、反転は行いません。判り易いように簡略化。


//MAINテキストアニメ
function set_mainanime() {

	略す

	//ループ
	for (var i=0; i < textlen; i++) {

		略す

		//ポイント固定
		if (movePoint) {
			textChip[i].x=guide_w;
			textChip[i].y=guide_h;
		}
		//X方向ポイント移動
		if (!movePoint) {
			textChip[i].x=guide_w+textPosx[i];
			textChip[i].y=guide_h;
		}

		略す

	}

	略す

}

パス制御ポイントの変更について

パス、制御ポイントなどの変更は行っていません。一律に同じガイドを使用しています。デモでは最終ポイントが固定ですので、当然パスの描画(ガイドパスデータ)が変わりますがそれなりの文字の動きになります。

パス制御ポイントを補正しながらアニメさせる事も可能かとは思いますが、2次ベジェ曲線ですから思い通りに滑らかには補正出来ないと推測します。補正したい方は補正しても構いません。


ワタシとしては、簡単でも適度に楽しめる動きになればよいと思っています。


Tweenの変更について

Tweenなどの操作、書き換えなどは自由です。「文字個別」「全文字」のTweenと2種が混同しています。アニメは、wait()で操作されていますのでその制御が重要になります。特に「文字個別」から「全文字」の切り替えのwaitの修正が大事です。
注意は、if文を使用する時にチェーンメソッドが使用できないのでエラーにならないように記載する位だ。
call()も旨く利用すれば応用変化を楽しめる。



delayの事前に最大値を求めておく
//delayの最大値を求める
var max_delay=Math.max.apply(null,delay_st);

----------------------------------------------------------

最大値を利用して時間差をなくすことにより文字全体を制御出来るようにする
.wait(max_delay-delay_st[i])
.wait(1000)

----------------------------------------------------------

文字全体から文字個別の制御は簡単です、全体で8秒まってから
文字個別の操作にしている
.wait(8000)
.wait(delay_st[i])


遅延に拠る文字列表示順序の制御

遅延とは wait() の使用である。ここでは delay と呼ぶことにするが、遅延を与えることにより文字要素の出現順序をかえている。(デモでは「ポイント固定」がわかるように文字列順だけにしている)
このデモでは、文字列順に表示しているが、下記のコードを有効にすれば、「逆順」「中から」「外から」と、文字表示順序を変えることが出来る。(画像分割の時の様に多くの種類の違いは出せない)


ランダムに条件を変える
//delay番号
var delay_no=Math.floor(Math.random()*4);

/*
if (delay_no == 0) {delay_st[i]=base_time*(sh-i);}//逆順
if (delay_no == 1) {delay_st[i]=Math.abs(i-sh/2)*base_time;}//中から
if (delay_no == 2) {delay_st[i]=Math.abs(Math.abs(i-sh/2)-textlen/2)*base_time;}//外から
*/

状態がわかり易い様、初期の大きさ scaleX scaleY は .1 にしていますが通常は 0 にします。その外全て、書き換え 追加 補正 など自由です。これに拡大、透明度、回転など組み合わせれば、モウ「お祭り騒ぎ」です。


一応、完動しますが全てテストです。効率化のため、予告無くJSなど修正する場合がありますので了承下さい。


テキストアニメーションは、以下の記事を参照下さい。

【参照】当方の記事: CreateJS 図形テキストをアニメーション、Tween 連続操作と MotionGuideTween の組み合わせ

【参照】当方の記事: CreateJS テキストアニメーション ランダム設定のテスト レインボー色(虹色)

【参照】当方の記事: CreateJS 図形を円周に配置した、サークルアニメーション、Tweenをwait()で連続操作する(虹色)


MotionGuide利用、テキストアニメーションのシミュレーション。

【参照】当方の記事: CreateJS MotionGuide利用、テキストアニメーションのシミュレーション


以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]