POPSブログ

CreateJS グラデーション図形を円周配置した、サークルアニメーション、Tween連続操作

237

  Category:  javascript2013/07/21 pops 

CreateJSを利用してキャンバス、サークル円周上にレインボー色(虹色)のグラデーション図形を配置表示します。前の「図形サークルアニメーション」と同じようなものですが、グラデーション装飾分前のものより重く成ります。
図形要素」毎のアニメと「図形全体」のアニメとの複合形式で「集合拡散」を連続して表現します。同じでは何ですから申し訳程度若干違わせています。
easeljs-0.7 でのテストです。

 

CreateJS グラデーション図形を円周配置、サークルアニメーション、Tween連続操作テスト


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


テキストアニメーションよりは軽く動作します。但しブラウザにより「回転精度」「描画品質」が違いますので注意下さい。全体の回転は可能ですがこのデモでは「回転」させていません。

 

[説明図]

サンプルには下記の形を用意しました。Circle. Star. Rect. RoundRect. Line. Leaf. Ellipse.

 

DEMO


CreateJS グラデーション図形を円周配置、サークルアニメーション、Tween連続操作 (createJS027b.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

createJS027b.js、JS名は任意に変更可。easeljs-0.7用


//日本語
//createJS027b.js
//easeljs-0.7用サークルアニメーション
//Circle rainbow-Color

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

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

//circle
var slice_value=24;//分割数
var base_angle=-90;//ベース角度補正
var range=360;//配置範囲レンジ角度 180 240 360

//図形インスタンス番号
//Circle=0 Star=1 Rect=2 RoundRect=3 Line=4 Leaf=5 Ellipse=6
var type_no=0;

//------------------------------------------------------
//変数、未使用もあり

//ステージ
var stage;
//box
var backrect;
var circlecontainer;

//TEXT
var viewtext;

//CircleBase
var circleBase;
//保存
var ballChip=[];
var ballPosx=[];
var ballPosy=[];

//Bung
var bangChip=[];

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

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

//サークル用グローバル変数
var partscount=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);

	//circle-Text circlecontainer
	circlecontainer=new createjs.Container();
	circlecontainer.x=canvasWidth/2;
	circlecontainer.y=canvasHeight/2;
	//ベース
	circleBase=new createjs.Container();
	circleBase.rotation=base_angle;//回転修正
	circlecontainer.addChild(circleBase);
	stage.addChild(circlecontainer);

	//簡易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("");
	set_circleparts();

}

//サークルアニメ
function set_circleparts() {

	ballChip=[];//クリア
	partscount=0;//カウント、グローバル

	var radius=canvasHeight/2*.8;//サークル半径
	//ベース
	circleBase=new createjs.Container();
	circlecontainer.addChild(circleBase);
	//ベース角度補正
	circleBase.rotation=base_angle;

	text_W=0;//全幅未使用

	//Bangインスタンス
	bangChip=[];
	for (var i=0; i < slice_value; i++) {
		bangChip[i]=createBang();
	}

	//インスタンス配列取得
	for (var i=0; i < slice_value; i++) {

		//Circleインスタンス
		if (type_no == 0) {
			//(x,y,r,color,rainbow,len,no)
			ballChip[i]=createBall(0,0,10,"#CCCCCC",true,slice_value,i);
		}
		//Starインスタンス
		if (type_no == 1) {
			//(x,y,r,color,rainbow,len,no)
			ballChip[i]=createStar(0,0,6,"#CCCCCC",true,slice_value,i);
		}
		//Rectインスタンス
		if (type_no == 2) {
			//(x,y,w,h,color,rainbow,len,no)
			ballChip[i]=createRect(0,0,20,20,"#CCCCCC",true,slice_value,i);
		}
		//RoundRectインスタンス
		if (type_no == 3) {
			//(x,y,w,h,r,color,rainbow,len,no)
			ballChip[i]=createRoundRect(0,0,20,20,4,"#CCCCCC",true,slice_value,i);
		}
		//Lineインスタンス
		if (type_no == 4) {
			//(x,y,w,h,color,rainbow,len,no)
			ballChip[i]=createLine(0,0,10,20,"#CCCCCC",true,slice_value,i);
		}
		//Leafインスタンス
		if (type_no == 5) {
			//(x,y,w,h,color,rainbow,len,no)
			ballChip[i]=createLeaf(0,0,30,30,"#CCCCCC",true,slice_value,i);
		}
		//Ellipseインスタンス
		if (type_no == 6) {
			//(x,y,w,h,color,rainbow,len,no)
			ballChip[i]=createEllipse(0,0,14,24,"#CCCCCC",true,slice_value,i);
		}

		//ポジション取得文字用に残す、未使用
		ballPosx[i]=0;
		ballPosy[i]=0;
	}

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

	//delay値保存配列
	var delay_st=[];
	var delay_st2=[];

	//パターン番号
	var pattern_no=Math.floor(Math.random()*5);
	//多目的判定用フラグ
	var chgxyflag=Math.floor(Math.random()*5);
	//多目的用2
	var chgflag=Math.floor(Math.random()*3);
	var chgflag2=Math.floor(Math.random()*3);
	//逆転フラグ
	var chg_v=Math.floor(Math.random()*2);
	if (chg_v < 1) {chg_v=-1;}

	var k=0;
	var flag=-1;
	var angle=0;
	var textwrap=[];

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

		angle =i*360/slice_value*range/360;//range展開角度1、0度より
		//angle +=360/slice_value*range/360;//range展開角度2、ズレ

		//WRAP
		var wrap=new createjs.Container();
		wrap.regX=0;
		wrap.regY=radius;
		wrap.x=0;
		wrap.y=0;
		wrap.rotation=angle;//angle;
		ballChip[i].x=0;
		ballChip[i].y=0;

		//移動
		ballChip[i].x=0;//0
		ballChip[i].y=radius*2*chg_v;

		//識別ID登録
		ballChip[i].id=i;

		ballChip[i].scaleX *=chgflag2;//0
		ballChip[i].scaleY *=chgflag2;//0
		ballChip[i].rotation=360*(chgflag2-1);//0
		ballChip[i].alpha=0;//1

		//addChild
		wrap.addChild(ballChip[i]);
		textwrap[i]=wrap;
		//addChild
		circleBase.addChild(textwrap[i]);

		k ++;
		flag *=-1;
	}

	//delay計算、delay逆転が効かない
	var k=0;
	var flag=-1;
	var sh=slice_value-1;
	var kk=0;
	for (var i=0; i < slice_value; i++) {
		kk=sh-i;

		//反対
		if (pattern_no == 0) {
			delay_st[i]=base_time*kk;
		}
		//中から
		if (pattern_no == 1) {
			delay_st[i]=Math.abs(i-sh/2)*base_time*1.5;
		}
		//外から
		if (pattern_no == 2) {
			delay_st[i]=i*base_time*1.5;
			if (i > sh/2) {delay_st[i]=kk*base_time*1.5;}
		}
		//正
		if (pattern_no > 2) {
			delay_st[i]=base_time*i;
		}
		//交互遅延確率増す
		if (chg_v > 0 ) {
			if (flag > 0) {
				delay_st[i] +=delayed_time;
			}
		}
		//交互遅延2
		delay_st2[i]=0;
		if (chg_v < 0 ) {
			if (flag > 0) {
				delay_st2[i] +=delayed_time;
			}
		}

		k ++;
		flag *=-1;
	}

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

	//収縮ポイント移動
	var radius_y=radius*(chgflag2-1);
	var scale_end=(chgflag-1)*2;

	//Tween
	for (var i=0; i < slice_value; i++) {
		//Tween
		var twn=createjs.Tween.get(ballChip[i])

		.wait(delay_st2[i])//delay2
		.to({x:0,y:radius*2.5,scaleX:1.5,scaleY:1.5,rotation:315*chg_v,alpha:0.5},2000)
		.wait(max_delay2-delay_st2[i])//最大値利用時間差吸収2
		.wait(600)
		.to({x:0,y:0,scaleX:1,scaleY:1,rotation:0,alpha:1},1600)

		.wait(delay_st[i])
		.to({x:0,y:radius_y,scaleX:0,scaleY:0,rotation:0,alpha:1},1200)
		.to({x:0,y:20,scaleX:.75,scaleY:.75,rotation:180,alpha:1},1000)
		.to({x:10*(chgflag2-1),y:0,scaleX:2,scaleY:2,rotation:45,alpha:1},500)
		.wait(250)
		.to({x:0,y:0,scaleX:1,scaleY:1,rotation:225,alpha:1},400)
		.wait(max_delay-delay_st[i])//最大値利用時間差吸収
		.to({x:0,y:-50,scaleX:1.5,scaleY:1.5,rotation:0,alpha:.5},800)
		.wait(600)
		.to({x:0,y:0,scaleX:1,scaleY:1,rotation:0,alpha:1},600)
		.wait(5000)
		.to({x:0,y:10*(chgflag2-1),scaleX:-2,scaleY:-2,rotation:315*chg_v,alpha:.5},1000)
		.wait(1000)
		.to({x:0,y:0,scaleX:1,scaleY:1,rotation:0,alpha:1},800)
		.wait(2000)
		.to({x:0,y:-20,scaleX:.5,scaleY:.5},400)
		.to({x:0,y:0,scaleX:1,scaleY:1},400)

		.wait(delay_st[i])
		.to({x:0,y:50*(chgflag-1),scaleX:.5,scaleY:.5,rotation:0,alpha:1},400)
		.call(bang_chg)//爆発
		.to({x:0,y:70*(chgflag-1),scaleX:5,scaleY:8,rotation:90,alpha:0},600)
		.wait(1000)

		.call(function(){
			//終了
			if (partscount == slice_value-1) {finshAll();}
			partscount +=1;//グローバルの事
		});
	}

}

//終了
function finshAll () {

	//END
	set_text("END");
	//調整
	setTimeout(function() {

		set_text("AUTO");
		reset_parts();

	},2000);
}

//要素graphics交換
function bang_chg() {
	var no=this.id;
	ballChip[no].graphics=bangChip[no].graphics;
}

//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);
}

//Circleインスタンスを作る
function createBall(x,y,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).drawCircle(x,y,r);

	//グラデ、小さいのでさほど効果なし
	//s.graphics.s().beginLinearGradientFill([c,"#FFFFFF"],[0,1],0,0,0,r*2).drawCircle(x,y,r);
	//重い
	s.graphics.s().beginRadialGradientFill(["#FFFFFF",c],[0.1,1.0],-3,3,0,0,0,r).drawCircle(x,y,r);

	//原点中央
	s.regX=0;
	s.regY=0;
	return s;
}
//Starインスタンスを作る
function createStar(x,y,r,color,rainbow,len,no) {
	var c=color;
	var c2=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
		c2=createjs.Graphics.getHSL(no/len*360,100,35);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).drawPolyStar(0,0,r,5,r/2,-90);
	//グラデ
	s.graphics.s().beginLinearGradientFill([c,c2],[0,1],0,0,0,r*2).drawPolyStar(0,0,r,5,r/2,-90);

	//原点中央
	s.regX=0;
	s.regY=0;
	return s;
}
//Rectインスタンスを作る
function createRect(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).drawRect(0,0,w,h);
	//グラデ
	s.graphics.s().beginLinearGradientFill(["#FFFFFF",c],[0,1],0,0,0,h).drawRect(0,0,w,h);

	//原点中央
	s.regX=w/2;
	s.regY=h/2;
	return s;
}
//RoundRectインスタンスを作る
function createRoundRect(x,y,w,h,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c);
	//ライン
	s.graphics.ss(2).s('#EEEEEE').beginFill(c);
	//Round修正
	operaRoundRect(s,x,y,w,h,r);
	//原点中央
	s.regX=w/2;
	s.regY=h/2;
	return s;
}
//Lineインスタンスを作る
function createLine(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//1本
	//s.graphics.ss(w,"round").s(c).moveTo(0,0).lineTo(0,h);
	//2本
	s.graphics.ss(w/2,"round").s(c).moveTo(-w/2,0).lineTo(-w/2,h).moveTo(w/2,0).lineTo(w/2,h);

	//原点中央
	s.regX=w/2;
	s.regY=h/2;
	return s;
}
//Leafインスタンスを作る
function createLeaf(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	var c2=color;//グラデ用
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
		c2=createjs.Graphics.getHSL(no/len*360,100,20);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).moveTo(w/2,0).quadraticCurveTo(w,h/2,w/2,h).quadraticCurveTo(0,h/2,w/2,0);
	//グラデ
	s.graphics.s().beginLinearGradientFill([c,c2],[0,1],0,0,w,h).moveTo(w/2,0).quadraticCurveTo(w,h/2,w/2,h).quadraticCurveTo(0,h/2,w/2,0);

	//原点中央
	s.regX=w/2;
	s.regY=h/2;
	return s;
}
//Ellipseインスタンスを作る
function createEllipse(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).drawEllipse(0,0,w,h);
	//グラデ
	s.graphics.s().beginLinearGradientFill(["#FFFFFF",c],[0,1],0,0,0,h).drawEllipse(0,0,w,h);

	//原点中央
	s.regX=w/2;
	s.regY=h/2;
	return s;
}
//reset_parts
function reset_parts() {

	set_text("CLEAR");

	//コンテナの中を削除
	circleBase.removeAllChildren();
	stage.update();

	//調整3000、長くした
	setTimeout(function() {
		set_prologue();
	},3000);

}

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

//quadraticCurveTo、こちら使用
function operaRoundRect(s,x,y,w,h,r) {
	s.graphics.moveTo(x+r,y)
	.lineTo(x+w-r,y)
	.quadraticCurveTo(x+w,y,x+w,y+r)
	.lineTo(x+w,y+h-r)
	.quadraticCurveTo(x+w,y+h,x+w-r,y+h)
	.lineTo(x+r,y+h)
	.quadraticCurveTo(x,y+h,x,y+h-r)
	.lineTo(x,y+r)
	.quadraticCurveTo(x,y,x+r,y);
}

//爆発要素line
function createBang(){
	var graphics=new createjs.Graphics();
	graphics.setStrokeStyle(1,"round").beginStroke("#CCCCCC");//round
	var cx,cy,
	numNeedles=7,
	innerR=11,
	outerR=10,
	cAngle= -Math.PI/2,
	nAngle;

	nAngle=Math.PI*2/numNeedles;
	for (var i=0; i < numNeedles; i++){
		cAngle +=nAngle;
		cx=Math.cos(cAngle)*innerR;
		cy=Math.sin(cAngle)*innerR;
		graphics.moveTo(cx,cy);
		cx=Math.cos(cAngle)*outerR;
		cy=Math.sin(cAngle)*outerR;
		graphics.lineTo(cx,cy);
	}
	var s=new createjs.Shape(graphics);
	return s
}

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

//START
init();

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


CSS

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


/*日本語 createJS027b.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;
}

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


簡単な説明


図形を円周上に配置する

基本的に、図形を並べた「サークルアニメーション」と同じですが、前ページのアニメの順序を反対にして最後は爆発するような感じにしました。遅延、修正など理解できれば自由に図形を操ることが可能です。
これらの手法は図形を横に並べた場合の操作にも応用できますから、変化に富んだ連続アニメーションを作れます。

前ページのJSの改造ですから、そちらも参照ください。


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


全体同時に動かす場合の交互遅延

雰囲気を変えるために、「全体同時」に動かす場合も「交互遅延」を最初に設定しましたが、個別に動かすのと同じになります。別途、「delay_st2」配列を用意してwait値を入れています。

wait()で連続して複数のインスタンスを動かしていますので、途中色々と小細工をしています。


最初の「全体同時」に動かすのに「交互遅延」させているので途中で時間を調整する。


//delay値保存配列
var delay_st2=[];

//交互遅延2
delay_st2[i]=0;
if (chg_v < 0 ) {
	if (flag > 0) {
		delay_st2[i] +=delayed_time;
	}
}

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

.wait(max_delay2-delay_st2[i])//最大値利用時間差吸収2

爆発の感じを出す

簡単ですが、インスタンスを取り替えています。ローデングを改造して使用しました。

インスタンスを取り替える場合、配列の値を代入すると使い回し出来ない場合もありますので注意下さい。clone()を使うと解決する場合など有ります。「デモ」ではその都度新規に作っています。


graphicsを代入して交換している。「デモ」では色は背景に白が有るため「爆発インスタンス」の色をグレーにしています。この辺は良い方法が有れば作ってください。ブラー処理して煙の様にするのも良いかも知れませんが止めときます。


.call(bang_chg)//爆発

//要素graphics交換
function bang_chg() {
	var no=this.id;
	ballChip[no].graphics=bangChip[no].graphics;
}

 

その他

DEMO専用です。使用する事は可能ですが、あくまでもテストですので個人の判断で使用下さい。画像などは各自ご用意下さい。JSの先頭部分をお読み下さい。
但し、効率的な方法があれば、予告無くスクリプトなど修正する場合があります、ご了承下さい。


以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]