POPSブログ

CreateJS Transition Mask 画像を複数のShapeでマスク処理してアニメ表示B

259

  Category:  javascript2013/11/10 pops 

複数のShapeで画像をマスクして、マスク材を動かしてエフェクトする Transition Mask です。画像分割と似通っていますが、多少視覚的に違いはあります。角形以外の図形でマスク出来るのが特徴でActionScriptでは「なじみ」のものです。前ページのものよりエフェクト数を増やしてみました。
easeljs-0.7 でのテストです。

 

CreateJS 画像を複数の分割Shape()でマスク処理してアニメ表示B テスト


前ページのものよりエフェクト数を増やしてみましたが、中のコードは「画像分割アニメ」のものとほぼ同じです。


[説明図]

 

1. 円形、角丸四角形、通常の四角形でマスクエフェクトします。
2. フェード、Skew(ひねり)処理も出来ますのでキレイです。
3. 移動位置、エフェクト数を増やしてみました。
4. 写真画像は一括読み込み形式です。
5. ナントカ動いている程度の代物です。

 

DEMO


CreateJS 画像を複数の分割Shape()でマスク処理してアニメ表示デモ、(createJS044.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/preloadjs-0.4.0.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.0.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。


HTML (HTML5)


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

JS

createJS044.js、JS名は任意に変更可。注意、easeljs-0.7用です。


//日本語
//createJS044.js
//Transition 一括画像ロード
//easeljs-0.7用

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

//Auto true false
var autoUse=true;
//タイマー値 5000-10000
var time=3000;
//TEXTの使用 true false
var textUse=true;
//最初の画像表示までの遅延時間
var wait_time=3000;//3000-8000

//アニメ速度
var shapemask_speed=1000;//Shapeマスク速度 800-1200
var delay_speed=150;//出現間隔、delay基準時間 100-200

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

//画像manifestリスト
var manifest=[
{src:"/main/images/flower01.jpg",id:"PHOTO"},
{src:"/main/images/flower02.jpg",id:"PHOTO"},
{src:"/main/images/flower03.jpg",id:"PHOTO"},
{src:"/main/images/flower04.jpg",id:"PHOTO"},
{src:"/main/images/flower05.jpg",id:"PHOTO"},
{src:"/main/images/flower06.jpg",id:"PHOTO"}
];


//---------------------------------
//マスク自動分割 true false
var maskSplit_free=true;//原則 true

//マスク自動分割でない場合の分割
var maskSplit_h=11;//標準の横方向分割数、奇数値
var maskSplit_v=5;//標準の縦方向分割数、奇数値
var maskSplit_all=maskSplit_h*maskSplit_v;

//マスク自動分割の場合、free分割データを登録/奇数値が良い
//マスク 1x1 は可能
var maskSplitHs=[10,11,11,6,11,11,21,1];
var maskSplitVs=[5,5,5,3,1,2,1,1];

//マスクスケール方向番号データ 0-3の値
var maskScales=[0,0,0,0,1,2,3];
//マスク回転データ、回転は120度x回転データ
var maskRotates=[0,0,0.0,1,1,2,3];

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

//最初の画像0のこと
var image_no=0;
//画像登録数
var image_max=0;

//ステージ
var stage;
//コンテナ
var welcomecontainer;
var backcontainer;
var container;
//Loader
var loader;

//画像result
var globalflag=false,topImage,backImage,mainImage,keep_mainImage,welcomeImage,timerID=null;
//画像保存
var keep_mainImage,errorImage;
//マスクBOX
var maskbox;
var overImage;
//Loading
var loadingShape;
//変数
//loading変数
var loading=false;
//ProgressBar
var progressbar;
var progtext;
var bar_v=0;
//TEXT
var viewtext;

//読み込み画像URL保存容器
var assets=[];

//----------------------------------------
//マスク分割大きさ位置保存容器
var maskChip_W=[],maskChip_H=[],maskChip_pos_X=[],maskChip_pos_Y=[];
//実際配置位置
var set_maskpos_X=[],set_maskpos_Y=[];
//移動配置位置
var mov_maskpos_X=[],mov_maskpos_Y=[];
//マスクスライスObject容器
var maskChip=[];
var maskkcount=0;
//----------------------------------------

//MASK-IMAGE
var img_st=[];
var maskalpha=false;

//変数
var inType=true;
//welcome画像読み込み判定
var welcomeflag=false;
var welcome_result;
var once=true;

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

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

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

	//STAGE
	stage=new createjs.Stage('mainCanvas');
	//MouseOver設定/必要に応じ設定
	//stage.enableMouseOver(20);

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

	//welcome画像層画像表示
	welcomecontainer=new createjs.Container();
	//welcome画像挿入
	if (welcomeflag) {
		welcomeImage=new createjs.Bitmap(welcome_result);
	} else {
		var gradient_data={x0:0,y0:canvasHeight/2,x1:0,y1:0};
		welcome_result=createGradientCanvas2 (canvasWidth,canvasHeight,"#DB7093","#FFFFFF",gradient_data,true,"Arial","bold 50px","#FFFFFF","WELCOME");
		welcomeImage=new createjs.Bitmap(welcome_result);
	}
	welcomecontainer.addChild(welcomeImage);
	stage.addChild(welcomecontainer);
	stage.update();
	
	//welcome画像保存
	keep_mainImage=welcome_result;

	//下画像層、空画像コンテナを作る
	backcontainer=new createjs.Container();
	backImage=new createjs.Bitmap();
	backcontainer.addChild(backImage);
	stage.addChild(backcontainer);
	
	//上画像層のみ作る
	container=new createjs.Container();
	//コンテナ00
	container.x=0;
	container.y=0;
	stage.addChild(container);

	//loadingコンテナを作る
	loadingcontainer=new createjs.Container();
	stage.addChild(loadingcontainer);
	//LOADINGを作る
	loadingShape=loadingIndicator();
	loadingShape.x=canvasWidth/2;
	loadingShape.y=canvasHeight/2;
	//tickを設定
	loadingShape.tick=function (){
		if(loading) {
			loadingShape.rotation +=5;
			stage.update();
		}
	}
	//loading addEventListenerを設定
	createjs.Ticker.addEventListener('tick',loadingShape.tick);
	//コンテナに貼り付け
	loadingcontainer.addChild(loadingShape);
	loading=true;//loading表示判定

	stage.update();

	//ProgressBar
	progresscontainer=new createjs.Container();
	progressbar=new createjs.Shape();
	progtext=new createjs.Text("0","12px Arial","#FFFFFF");
	progtext.x=0;
	progtext.y=15;
	progtext.maxWidth=80;
	progtext.textAlign="center";
	progtext.shadow=shadow;//shadow
	//alpha
	progressbar.alpha=0.5;

	//bar_v判定tickを設定 butt round/Stroke
	//90度是正-Math.PI/2
	progressbar.tick=function (){
		if(bar_v > 0) {
			progressbar.graphics.clear();
			progressbar.graphics.setStrokeStyle(8,"butt").beginStroke("#FF69B4");
			progressbar.graphics.arc(0,0,40,-Math.PI/2,Math.PI*2*bar_v-Math.PI/2);
			progtext.text=Math.floor(bar_v*100);
			stage.update();
		}
	}
	//Ticker.Listener設定
	createjs.Ticker.addEventListener('tick',progressbar.tick);
	//addChild
	progresscontainer.x=canvasWidth/2;
	progresscontainer.y=canvasHeight/2;
	progresscontainer.addChild(progressbar,progtext);
	stage.addChild(progresscontainer);

	//簡易TEXT
	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");
	//bulk-load、画像一括ロードに進む
	bulkload();
}

//progressBar
function progress(event) {

	//loadedのみ効く
	bar_v=event.loaded;
}

//bulk-load、画像一括ロード
function bulkload() {

	set_text("Loading Now!");

	//Loaderを作る
	loader=new createjs.LoadQueue(false);
	//全体、progressがあれば先に設定
	loader.addEventListener("progress",progress);

	//loader EventListener設定
	loader.addEventListener("fileload",fileload);
	loader.addEventListener("complete",complete);

	//Manifestを使用、manifest読み込み開始
	loader.loadManifest(manifest);

}

//各画像読み込み完了
function fileload (event) {

	//エラー無しの画像をassets容器に保存
	assets.push(event.result);

}
//全ての画像読み込み完了
function complete (event) {

	set_text("Loaded!");

	//画像数確認、再計算
	image_max=assets.length;
	//簡易TEXT
	set_text("Loading End!");
	//loader Listener削除
	loader.removeEventListener("fileload",fileload);
	loader.removeEventListener("complete",complete);

	//loading EventListener削除
	createjs.Ticker.removeEventListener('tick',loadingShape.tick);
	//非表示でも良い
	loadingcontainer.visible=false;
	loading=false;//loading表示判定

	stage.update();

	//画像があれば、最初の画像表示
	if (image_max > 0) {

		//早すぎるので調整
		setTimeout(function() {

			//遅延progressbar最後の前にcompleteが反応する
			event.target.removeEventListener("progress",progress);
			//progressTicker削除
			createjs.Ticker.removeEventListener('tick',progressbar.tick);
			//progress非表示
			progresscontainer.visible=false;

			//簡易TEXTクリア
			set_text("");
			//viewtext.visible=false;

			stage.update();
			//画像表示に進む
			draw_image();

		},wait_time);
	}
}

//アニメ分岐
function draw_image() {

	//IN OUTを確率で決定
	inType=true;
	var in_no=Math.floor(Math.random()*2);
	if (in_no == 0) {inType=false;}

	//TEXT/AUTO
	set_text("IMAGE "+(image_no+1));

	//keep値が無ければ強制IN
	if (!keep_mainImage) {inType=true;}

	//INの場合画像result取得
	if (inType) {
		mainImage=assets[image_no];
	} else {
		//OUTの場合画像keep.result取得
		mainImage=keep_mainImage;
	}

	keep_mainImage=assets[image_no];
	
	//処理に進む
	shapemask_anime();

}

//マスクshapemaskアニメ
function shapemask_anime() {

	globalflag=false;//未使用
	//カウントクリア
	maskkcount=0;
	var splitNo=0;//マスク番号

	//マスク分割変更
	if (maskSplit_free) {
		splitNo=Math.floor(Math.random()*maskSplitHs.length);
		//分割値代入
		maskSplit_h=maskSplitHs[splitNo];
		maskSplit_v=maskSplitVs[splitNo];
	}

	//マスクスライス寸法データを得る
	sliceMask_set(canvasWidth,canvasHeight,maskSplit_h,maskSplit_v);
	//分割合計要素数計算
	maskSplit_all=maskSplit_h*maskSplit_v;

	//マスクChip
	maskChip=[];
	//MASK-IMAGE
	img_st=[];
	//カスタムマスクChip
	var customChip=false;
	//カスタムマスク拡大率
	var rate_v=1;

	var k=0;
	for (var i=0; i < maskSplit_h; i++) {
		for (var j=0; j < maskSplit_v; j++) {

			//shape
			maskChip[k]=new createjs.Shape();
			maskChip[k].width=maskChip_W[k];
			maskChip[k].height=maskChip_H[k];
			maskChip[k].id=k;
			//中央補正/分割保存値を使用のこと
			maskChip[k].regX=maskChip_W[k]/2;
			maskChip[k].regY=maskChip_H[k]/2;

			//角形
			if (splitNo > 1) {
				maskChip[k].graphics.beginFill().drawRect(0,0,maskChip_W[k],maskChip_H[k]);
			}
			//円楕円
			if (splitNo == 0) {
				maskChip[k].graphics.beginFill().drawEllipse(0,0,maskChip_W[k],maskChip_H[k]);
				rate_v=1.5;//拡大率
				customChip=true;
			}
			//角丸
			if (splitNo == 1) {
				maskChip[k].graphics.beginFill();
				operaRoundRect(maskChip[k],0,0,maskChip_W[k],maskChip_H[k],10);
				rate_v=1.1;//拡大率
				customChip=true;
			}

			k++;
		}
	}

	//アニメ条件設定
	//配列クリア
	var delay_st=[];
	var delay_pt=[];
	//rotation受渡変数配列
	var rotate_v=[];

	//多目的判定用
	var chgxyflag=Math.floor(Math.random()*5);
	//多目的用2
	var chgflag=Math.floor(Math.random()*3);
	//多目的判定用3 1-2の値
	var chgflag2=Math.floor(Math.random()*2)+1;

	//多目的用4
	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()*12);//11-12
	//delayed遅延させる/20%
	var delayed=Math.floor(Math.random()*5);

	//半径、幅の70%で外側配置に使用
	var radius=Math.floor(canvasWidth*0.7);

	//透明度
	var alpha_no=Math.floor(Math.random()*2);

	//配置disposition位置
	var disposition_no=Math.floor(Math.random()*9);
	var disposition_X=0;
	var disposition_Y=0;

	//スケール方向番号
	var scale_no = maskScales[Math.floor(Math.random()*maskScales.length)];
	var scale_X=0;
	var scale_Y=0;

	//回転データ取得
	var rotate=maskRotates[Math.floor(Math.random()*maskRotates.length)];

	//ひねりskew確率33%
	var skew_no=Math.floor(Math.random()*3);
	var skewx_v=0;
	var skewy_v=0;
	var skewflag=false;//判定
	//splitNo 0-2に処理
	if (skew_no == 1 && splitNo < 3) {
		skewflag=true;
		rotate=0;//回転0
		var skewx_v=90*(chgflag2-1)*chg_v;
		var skewy_v=90*chg_v*-1;
		if (!inType) {scale_no=0;}//重要
	}

	//radius半径補正、20% 円形の内部位置になる/強制透過
	if (chgxyflag == 0) {radius *=0.5;}

	//カスタムマスク補正
	if (customChip) {alpha_no=0;}

	//Even算出
	var even_v = 1;
	if (maskSplit_v % 2 != 0) {even_v = 0;}

	//配置条件設定
	flag3=1;
	var v_x;
	var v_y;
	var k=0;
	for (var i=0; i < maskSplit_h; i++) {
		for (var j=0; j < maskSplit_v; j++) {

			//戻り位置計算
			set_maskpos_X[k]=maskChip_pos_X[k]+maskChip_W[k]/2;
    			set_maskpos_Y[k]=maskChip_pos_Y[k]+maskChip_H[k]/2;

			//移動加算値等の計算
			switch(disposition_no){
				case 0://その場所で
					disposition_X=set_maskpos_X[k];
					disposition_Y=set_maskpos_Y[k];
					//スケール補正
					scale_no=0;alpha_no=0;
					//skew処理
					if (splitNo > 2 && chgxyflag == 2) {
						scale_no=4;alpha_no=1;rotate=0;chgflag=0;delay_no=0;
					}
				break;
				case 1://外側に、radius半径
					var angle=Math.random()*360;
					disposition_X=Math.cos(angle)*radius+(canvasWidth/2);
					disposition_Y=Math.sin(angle)*radius+(canvasHeight/2);
				break;
				case 2://左右に中心から補正/カスタム補正
					v_x=(canvasWidth/2+maskChip_W[k]/2*rate_v)*chg_v;
					disposition_Y=set_maskpos_Y[k];
					if (!chgflag && i % 2 != 0) {v_x *=-1;}
					if (chgxyflag < 2) {v_x *=flag3;}
					disposition_X=v_x+(canvasWidth/2*rate_v);
				break;
				case 3://上下に中心から補正/カスタム補正
					disposition_X=set_maskpos_X[k];
					v_y=(canvasHeight/2+maskChip_H[k]/2*rate_v)*chg_v;
					if (!chgflag && j % 2 != 0) {v_y *=-1;}
					if (chgxyflag < 2) {v_y *=flag3;}
					disposition_Y=v_y+(canvasHeight/2*rate_v);
				break;
				case 4://YX内部ランダム位置
					disposition_X=Math.floor(Math.random()*canvasWidth);
					disposition_Y=Math.floor(Math.random()*canvasHeight);
					//スケール補正
					scale_no=0;
				break;
				case 5://中央
					disposition_X=canvasWidth/2;
					disposition_Y=canvasHeight/2;
					if (!chgflag) {disposition_X=set_maskpos_X[k];}
					//スケール補正
					scale_no=0;
				break;
				case 6://YX内部ランダム位置2
					disposition_X=Math.floor(Math.random()*canvasWidth);
					if(maskSplit_all == 1) {disposition_X=canvasWidth/2;}//1枚画像補正
					disposition_Y=canvasHeight/2;
					//スケール補正
					if (splitNo <= 2 ) {scale_no=0;}
					if (splitNo > 2 ) {scale_no=3;}
				break;
				case 7://内部2点から
					if (flag3 < 0) {disposition_X=canvasWidth/4;}
					else {disposition_X=canvasWidth*3/4;}
					disposition_Y=canvasHeight/2;
					//スケール補正
					scale_no=0;
				break;
				default://そのほか
					disposition_X=set_maskpos_X[k];
					disposition_Y=set_maskpos_Y[k];
					//スケール補正
					scale_no=0;
			}

			//スケール方向決定
			switch(scale_no){
				case 0:
					scale_X=0;scale_Y=0;
				break;
				case 1:
					scale_X=1;scale_Y=1;
					//INでrotationなら食み出すので強制透明度設定
					if (inType && rotate > 0) {alpha_no=0;}
				break;
				case 2:
					scale_X=0;scale_Y=1;
				break;
				case 3:
					scale_X=1;scale_Y=0;
				break;
				case 4:
					if (inType) {
						if (chgflag3 == 0) {scale_X=0;scale_Y=1;skewx_v=30*chg_v;skewy_v=0;}
						if (chgflag3 == 1) {scale_X=1;scale_Y=0;skewx_v=0;skewy_v=30*chg_v;}
						if (chgflag3 == 2) {scale_X=0;scale_Y=0;skewx_v=90*chg_v;skewy_v=90*chg_v*-1;}
					}
					if (!inType) {
						if (chgflag3 == 0) {scale_X=1;scale_Y=0;skewx_v=30*chg_v;skewy_v=0;}
						if (chgflag3 == 1) {scale_X=0;scale_Y=1;skewx_v=0;skewy_v=30*chg_v;}
						if (chgflag3 == 2) {scale_X=0.5;scale_Y=0.5;skewx_v=45*chg_v;skewy_v=45*chg_v*-1;}
					}
					skewflag=true;

				break;
				default:
					scale_X=0;scale_Y=0;
			}

			//rotation値の決定 120度x、逆転有り
			rotate_v[k]=rotate*120*chg_v;
			//回転の変化、回転0以外なら交互逆転する、確率33%
			if (chgflag == 1) {rotate_v[k] *=flag3;}
			//skew交互逆転、気づかない
			if (chgflag == 1 && skewflag) {skewx_v *=flag3;skewy_v *=flag3;}

			//カスタムマスクChip拡大補正
			var outscale_X=1;
			var outscale_Y=1;
			//拡大率rate設定
			if (customChip) {outscale_X=rate_v;outscale_Y=rate_v;}

			//初期の移動
			//IN
			if (inType) {
				mov_maskpos_X[k]=disposition_X;
				mov_maskpos_Y[k]=disposition_Y;
				maskChip[k].x=mov_maskpos_X[k];
    				maskChip[k].y=mov_maskpos_Y[k];
				maskChip[k].rotation=rotate_v[k];
				maskChip[k].scaleX=scale_X;
				maskChip[k].scaleY=scale_Y;
				maskChip[k].alpha=1;//1
				//skew
				maskChip[k].skewX=skewx_v;
				maskChip[k].skewY=skewy_v;
			}

			//OUT
			if (!inType) {
				mov_maskpos_X[k]=disposition_X;
				mov_maskpos_Y[k]=disposition_Y;
				maskChip[k].x=set_maskpos_X[k];
    				maskChip[k].y=set_maskpos_Y[k];
				//初期の条件
				maskChip[k].rotation=0;
				maskChip[k].scaleX=outscale_X;//カスタム補正
				maskChip[k].scaleY=outscale_Y;
				maskChip[k].alpha=1;//1
				//skew
				maskChip[k].skewX=0;
				maskChip[k].skewY=0;
			}

			//表示リストaddChild、stage.updateはしないこと
			//コンテナに収容
			container.addChild(maskChip[k]);

			k++;
			flag3 *=-1;
		}
		if (even_v) {flag3 *=-1;}
	}

	//delayの計算/通常より増やした
	var sh=maskSplit_h-1;
	var sv=maskSplit_v-1;

	var flag3=1;
	var kk=0;//方向違いカウント
	var kkk=0;//半分でカウントダウン
	var k=0;
	for (var i=0; i < maskSplit_h; i++) {
		for (var j=0; j < maskSplit_v; j++) {

			//縦方向にカウント
			kk=i*maskSplit_v+j;
			kkk=k;
			if (k > (maskSplit_all-1)/2) {kkk=Math.abs(maskSplit_all-k)-1;}

			if (delay_no == 0) {delay_st[k]=(i+j)*delay_speed;}
			if (delay_no > 0 && delay_no < 5) {delay_st[k]=(i+j+k/maskSplit_all/4)*delay_speed;}//滑らか
			if (delay_no == 5) {delay_st[k]=(i+j)/2;delayed=1;}
			if (delay_no == 6) {delay_st[k]=kk*delay_speed;}
			if (delay_no == 7) {delay_st[k]=kkk*delay_speed;}
			if (delay_no == 8) {delay_st[k]=(Math.abs(Math.abs(i-sh/2)-sh)+Math.abs(Math.abs(j-sv/2)-sv))*2*delay_speed;}//円形状外から中心に
			if (delay_no == 9) {delay_st[k]=(Math.abs(i-(sh/2))-Math.abs(j-(sv/2)))*3*delay_speed;}//対角組あわせX状に
			if (delay_no == 10) {delay_st[k]=Math.floor(Math.random()*maskSplit_all)/2*delay_speed;}//適当なランダム
			//追加、対角中より外に/対角方向違い
			if (delay_no == 11) {delay_st[k]=Math.abs(j*maskSplit_h/maskSplit_v-Math.abs(i-sh)*chg_v)*1.5*delay_speed;}
			if (delay_no > 11 ) {delay_st[k]=k*2*delay_speed;}

			//分割数が少ない場合早いので、間隔をあける1.5-3
			if (maskSplit_all < 16) {delay_st[k] *=2;}

			//delayed遅延
			if (delayed == 1) {
				if (flag3 < 0) {delay_st[k] +=1000;}
			}

			k++;
			flag3 *=-1;

		}
		if (even_v) {flag3 *=-1;}
	}

	//画像配置
	var k=0;
	for (var i=0; i < maskSplit_h; i++) {
		for (var j=0; j < maskSplit_v; j++) {

			img_st[k]=new createjs.Bitmap(mainImage);
			img_st[k].mask=maskChip[k];
			if (inType) {img_st[k].alpha=alpha_no;}
			if (!inType) {img_st[k].alpha=1;}
			container.addChild(img_st[k]);

			k++;
		}
	}

	//delay反転
	if (chgxyflag > 2) {
		delay_st.reverse();
	}

	//maskの透明度を変えるか50%
	maskalpha=false;
	if (alpha_no == 0) {maskalpha=true;}

	//OUTの場合下画像を入れるstage.updateはしないこと
	if (!inType) {
		backImage.image=new createjs.Bitmap(keep_mainImage).image;
	}

	//Easeの変更 IN最後遅くOUT等速
	var ease=createjs.Ease.linear;
	if (inType) {ease=createjs.Ease.cubicOut;}

	//TWEENの実行/重ね順は変更しない
	var k=0;
	var params={};
	for (var i=0; i < maskSplit_h; i++) {

		for (var j=0; j < maskSplit_v; j++) {

			if (inType) {
				params={x:set_maskpos_X[k],y:set_maskpos_Y[k],scaleX:outscale_X,scaleY:outscale_X,rotation:0,skewX:0,skewY:0};
				img_st[k].alpha=alpha_no;
			}
			if (!inType) {
				params={x:mov_maskpos_X[k],y:mov_maskpos_Y[k],scaleX:scale_X,scaleY:scale_Y,rotation:rotate_v[k],skewX:skewx_v,skewY:skewy_v};
				img_st[k].alpha=1;
			}

			var tween=createjs.Tween.get(maskChip[k])
			.wait(delay_st[k])
			.call(alphachg)
			.to(params,shapemask_speed,ease)
			.to({rotation:0},1)
			.call(finshMasktween);

			k++;

		}
	}

	//Ticker設定
	createjs.Ticker.setFPS(20);
	createjs.Ticker.addEventListener('tick',tick);

}

//マスクスライスalphaTween
function alphachg (event) {
	if (!maskalpha) {return}
	var twn=createjs.Tween.get(img_st[this.id]);
		if (inType) {
			twn.to({alpha:1},shapemask_speed);
		}
		if (!inType) {
			twn.to({alpha:0},shapemask_speed);
		}
}

//マスクスライス要素の位置大きさ決定、保存
function sliceMask_set(bw,bh,slh,slv) {

	//マスクスライス
	slice_W=Math.round(bw/slh);//YOKO
	slice_H=Math.round(bh/slv);//TATE
	slice_Wb=bw-slice_W*(slh-1);
	slice_Hb=bh-slice_H*(slv-1);
	var k=0;
	for (var i=0; i < slh; i++) {
		for (var j=0; j < slv; j++) {
			//大きさ保存
			maskChip_W[k]=slice_W;
			if (i == slh-1) {maskChip_W[k]=slice_Wb;}
			maskChip_H[k]=slice_H;
			if (j == slv-1) {maskChip_H[k]=slice_Hb;}
			//位置保存中央補正前
			maskChip_pos_X[k]=(slice_W*i);
			maskChip_pos_Y[k]=(slice_H*j);
			k ++;
		}
	}
}

//マスク個別のアニメ完了
function finshMasktween () {

	//全て完了
	if(maskkcount == maskSplit_all-1) {
		//画像alpha処理調整
		setTimeout(function(){
			finshAll();
		},200);
	}
	//0からカウント加算
	maskkcount ++;
}

//アニメ完了
function finshAll () {

	//Tween全てが完了してから下画像表示
	if (inType) {
		backImage.image=new createjs.Bitmap(mainImage).image;
		stage.update();
	}

	set_text("END");

	//removeAllTweens必要なら
	createjs.Tween.removeAllTweens();
	//上画像コンテナの中を削除
	container.removeAllChildren();

	//welcome表示中なら削除、遅延して削除している
	if(welcomeImage.visible) {
		stage.removeChild(welcomeImage);
	}
	//once
	if (once) {once=false;}
	//クリア
	maskkcount=0;

	//画像処理に時間がかかるので、少し遅延させる、あったほうが良い
	setTimeout(function(){

		//Ticker削除
		createjs.Ticker.removeEventListener('tick',tick);

		//AUTO
		if (autoUse) {
			set_text("AUTO");
			set_timer();
		}

	},1000);//長い

}

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

//次ぎの開く要素を計算
function next_set() {

	//次ぎの番号
	image_no +=1;
	if (image_no > (image_max-1)) {image_no=0;}
	draw_image();

}

//タイマー
function set_timer() {

	//一旦切ってからセット
	clearTimeout(timerID);
	timerID=setTimeout(next_set,time);
}

//VIEWTEXT
function set_text(t) {
	if (textUse) {
		viewtext.text=t;
		stage.update();
	}
}

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

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

//幅、高さ、色、フォント作る、文字種、サイズ、文字色、ストリング
function createGradientCanvas2 (w,h,c,c2,data,make,font,fsize,fcolor,text) {

	//data
	var x0=data.x0;
	var y0=data.y0;
	var x1=data.x1;
	var y1=data.y1;
	//
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//(0,h/2,0,0)
	var gradient=ctx.createLinearGradient(x0,y0,x1,y1);
	gradient.addColorStop(0,c);
	gradient.addColorStop(1,c2);
	ctx.fillStyle=gradient;
	ctx.rect(0,0,w,h);
	ctx.fill();

	if (make) {

		var font_v=fsize +" "+ font;

		ctx.fillStyle=fcolor;
		ctx.font=font_v;
		ctx.textAlign="center";
		ctx.textBaseline="middle";
		ctx.fillText(text,w/2,h/2);

	}

	return canvas;
}

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

//簡単なLOADING
function loadingIndicator(){

	//graphicのスタイル
	var graphics=new createjs.Graphics();
	graphics.setStrokeStyle(2,"round").beginStroke("#CCCCCC");//round

	//描画データ
	var cx,cy,
	numNeedles=12,
	innerR=10,
	outerR=5,
	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);
	}
	//Shapeに格納
	var s=new createjs.Shape(graphics);
	return s
}

//START
window.onload=function() {
	var img=new Image();
	img.src='/main/images/welcome_back5.png';
	img.onload=function () {
		welcome_result=img;
		welcomeflag=true;
		init();
	};
	img.onerror=function () {
		welcome_result=img;
		welcomeflag=false;
		init();
	};
};

注釈文を削除すれば、幾分早くなります。
登録画像パスは当方の場合です。使用の際は環境に合わせて下さい。


CSS

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


/*日本語 createJS044.css*/

#demo-wrap {
text-align:center;
}

#image-box {
position:relative;
top:0;left:0;
width:640px;
height:300px;
margin:0 auto;
padding:0;
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:#FFFFFF;
}

#image-box #mainCanvas {
border-radius:10px;
}
canvas {
border-style:none;
background-color:transparent;
}

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

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


簡単な説明


複数のマスク材によるマスク

この所の詳細は、前頁の説明を参照下さい。


【参照】当方の記事: CreateJS TransitionMask 画像を複数の分割Shape()でマスク処理してアニメ表示する


画像分割アニメ処理と同じです

「画像分割アニメ処理」と全く同じ処理ですが、2つ同時に動かす場合を想定して、変数などを違わせて再利用しています。(少し違わせれば其のままでも使用できます、画像を動かすか、マスク要素を動かすかの違いだけ)
「画像分割アニメ」と見た目は結構同じに見えますので、ひねりSkew処理を加えています。


1. AS3でもその場で移動しないでの処理が多い。移動させる分処理が面倒になります。
(「画像分割」と違い、マスクが重なっている部分の変化は見えないので効果は半減します)
2. IN OUT の区分をして処理する例は殆んどないと思います。
(当方では面倒でも IN OUT の2系統で処理が多い)
3. マシン性能に左右されるが、Chromeでは見た目良くない。(他はキレイです)


画像寸法などの変更

画像寸法などの変更に伴い、マスクが完全にカバー出来ない場合は、下記の「拡大率」を変えて合わせて下さい。
マスクは画面を分割した大きさに描かれますので、マスク仕切れない部分が出るために拡大して使用しています。


	//円楕円
	if (splitNo == 0) {
		maskChip[k].graphics.beginFill()..............
		rate_v=1.5;//拡大率
		customChip=true;
	}
	//角丸
	if (splitNo == 1) {
		maskChip[k].graphics.beginFill();
		operaRoundRect........
		rate_v=1.1;//拡大率
		customChip=true;
	}

分割の変更

基本的には自由に分割は出来ますが、1番目-3番目は「正方形に近い」同じ分割にして下さい。その後は自由です。
デモ画面の大きさで、下記分割合計(11x5=55)に成ります。分割合計は50-60位で有りマシン環境が良ければ最大80位までにして下さい、但しFlash並の動作はしませんので動作するか確認の事。
配列 maskSplitHs の登録数よりランダムな番号でその都度選定されアニメ処理されます。


var maskSplitHs=[11,11,11,6,11,11,21,1];//横
var maskSplitVs=[5,5,5,3,1,2,1,1];//縦

1番目-3番目は予約されていますので、その後の動作とは違います。3番目以降同じ分割があれば確率がまします。
アニメの条件もランダムに選定実行されますので、登録の分割にあった動きをする訳では有りません。其れなりです。


スケール方向の変更

マスク要素の伸縮は、伸縮方向によって次ぎの番号を定め実行しています。原点は全て中心です。

 

基本的には登録の「マスクスケール方向番号データ」からランダムに選定されて実行されますが、途中で半数が 0番に強制変更されています。
スケール方向番号 1,2,3 を増やせば、「分割番号1番目-3番目」以外で違った動きになる場合があります。


//マスクスケール方向番号データ 0-3の値
var maskScales=[0,0,0,0,1,2,3];

欄外にの移動

表示領域外に移動の場合は、図形の拡大率を考慮した位置にしないと、画面(表示領域)に残る事があるので注意が必要です。円、角丸などの図形を拡大で無理に配置している弊害です。



	//移動加算値等の計算
	switch(disposition_no){
		case 2://左右に中心から補正/カスタム補正
			v_x=(canvasWidth/2+maskChip_W[k]/2*rate_v)*chg_v;
			disposition_Y=set_maskpos_Y[k];
			if (!chgflag && i % 2 != 0) {v_x *=-1;}
			if (chgxyflag < 2) {v_x *=flag3;}
			disposition_X=v_x+(canvasWidth/2*rate_v);
		break;
		case 3://上下に中心から補正/カスタム補正
			disposition_X=set_maskpos_X[k];
			v_y=(canvasHeight/2+maskChip_H[k]/2*rate_v)*chg_v;
			if (!chgflag && j % 2 != 0) {v_y *=-1;}
			if (chgxyflag < 2) {v_y *=flag3;}
			disposition_Y=v_y+(canvasHeight/2*rate_v);
		break;
	}

ひねりSkew処理1

splitNo 0-2 多分割11x5の場合のSkew処理ですが、条件を変えればどの分割にも適用変更可能ですが、円形の場合はマスクゆえに変化の見えない時もあります。(90 0 -90 が適当に組み合わさる様に計算)

「ひねり」処理の時は、通常の「回転」で効果が打ち消される場合があるので、回転を行わない様にしている。


	//ひねりskew確率33%
	var skew_no=Math.floor(Math.random()*3);
	var skewx_v=0;
	var skewy_v=0;
	var skewflag=false;//判定
	//splitNo 0-2に処理
	if (skew_no == 1 && splitNo < 3) {
		skewflag=true;
		rotate=0;//回転0
		var skewx_v=90*(chgflag2-1)*chg_v;
		var skewy_v=90*chg_v*-1;
		if (!inType) {scale_no=0;}//重要
	}

ひねりSkew処理2

上のsplitNo 0-2以外のSkew処理を行います。IN OUT で振る舞いが少し違うので、それぞれ合うようにしています。
どちらのSkew処理にしても適当に変化する様にしているだけですから、分割数などの条件によっては合わない事もあります。多少の変化が出来る程度と考えてください。


	//スケール方向決定
	switch(scale_no){
		case 0:
			scale_X=0;scale_Y=0;
		break;

			略す

		case 4:
			if (inType) {
				if (chgflag3 == 0) {scale_X=0;scale_Y=1;skewx_v=30*chg_v;skewy_v=0;}
				if (chgflag3 == 1) {scale_X=1;scale_Y=0;skewx_v=0;skewy_v=30*chg_v;}
				if (chgflag3 == 2) {scale_X=0;scale_Y=0;skewx_v=90*chg_v;skewy_v=90*chg_v*-1;}
			}
			if (!inType) {
				if (chgflag3 == 0) {scale_X=1;scale_Y=0;skewx_v=30*chg_v;skewy_v=0;}
				if (chgflag3 == 1) {scale_X=0;scale_Y=1;skewx_v=0;skewy_v=30*chg_v;}
				if (chgflag3 == 2) {scale_X=0.5;scale_Y=0.5;skewx_v=45*chg_v;skewy_v=45*chg_v*-1;}
			}
			skewflag=true;
			break;

			略す

			default:
				scale_X=0;scale_Y=0;
	}

透明度の補正

一番問題になるのは、回転を与えている場合に画面内に食み出してしまう事です。その為に初期状態でスケールが「XY方向とも1」は、透明度を強制的に与えて見えなくします。
OUTの場合はINに透明度があれば設定されますが、大事をとって最後に、回転を瞬間的に 0 にします。

ランダムな条件で動かしているために、不具合にキズクのが遅れる場合があります。機能を加えたり複雑にすればする程大変になります。


INの場合の修正

	//スケール方向決定
	switch(scale_no){
		case 1:
			scale_X=1;scale_Y=1;
			//INでrotationなら食み出すので強制透明度設定
			if (inType && rotate > 0) {alpha_no=0;}
		break;
	}

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

OUTの場合の修正

	var tween=createjs.Tween.get(maskChip[k])
	.wait(delay_st[k])
	.call(alphachg)
	.to(params,shapemask_speed,ease)
	.to({rotation:0},1)
	.call(finshMasktween);

指定色のグラデーション代替画像を作る

Welcome画像を取得出来ずに、指定色のグラデーション代替画像を作る場合です。Welcome画像があれば最初「OUT」の処理が出来るだけですが、、
グラデーションの設定、gradient_data は html5 Canvas の規定によります。


[ 線形グラデーションオブジェクト ]
線形グラデーションオブジェクトを生成する
ctx.createLinearGradient (x0,y0,x1,y1)



上が白で下が、指定色のグラデーション代替画像を作る
var gradient_data={x0:0,y0:canvasHeight/2,x1:0,y1:0};
//幅、高さ、色、色2、DATA、フォント作る、文字種、サイズ、文字色、ストリング
canvasImage=createGradientCanvas2 (canvasWidth,canvasHeight,"#DB7093","#FFFFFF",gradient_data,true,"Arial","bold 30px","#FFFFFF","IMAGE NONE");

上が、指定色で下が黒のグラデーション
var gradient_data={x0:0,y0:canvasHeight,x1:0,y1:canvasHeight*0.6};
//幅、高さ、色、色2、DATA、フォント作る、文字種、サイズ、文字色、ストリング
canvasImage=createGradientCanvas2 (canvasWidth,canvasHeight,"#000000","#DB7093",gradient_data,true,"Arial","bold 30px","#FFFFFF","IMAGE NONE");

第5引数、gradient_dataは、始点と終点、(x0,y0,x1,y1)を {} で記載した
第6引数、フォント作る true 作らない false
第8引数、フォントの 斜体 太さ 大きさ を指定する、例、"italic bold 32px"


 

画像

画像は各自用意ください。Welcome画像 640x300サイズ、写真画像 640x300サイズ


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


以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]