POPSブログ

CreateJS Transition Mask マスク要素を組み合わせてアニメ表示する、番外編

262

  Category:  javascript2013/11/25 pops 

複数の形状の違うマスク要素を組み合わせてマスクで画像エフェクトする Transition Mask 番外編です。マスク要素をシェイプトゥイーンもどきでグラフイックをカキカエ、マスクを着色して変化させる「お病気系エフェクト」です。
easeljs-0.7 でのテストです。

 

CreateJS Transition Mask マスク要素を組み合わせてアニメ表示する、番外編テスト


マスクの分割の形式が違うのみで、処理の流れ、コードなどは通常のTransition Maskのものとほぼ同じです。
やる事がなくなると、平常心を失い色々と暴挙的エフェクトとなるのが常である。アイデアとは程遠い感じです。


[説明図]

 

1. 通常の分割方式で作り、マスク要素をシェイプトゥイーンもどきでグラフイックをカキカエ。
(処理が重なるので動作が重く、ゴマカシで品質は良くない)
2. マスクを着色して変化をさせると言う暴挙を実行します。
3. 番外編テストですのでイイカゲンなものです。
4. Chromeでのマスクはアンチエイリアス(anti-aliasing)処理が効きませんので見栄えは最低です。

 

DEMO


CreateJS Transition Mask マスク要素を組み合わせてアニメ表示する、番外編デモ、(createJS047.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="300"></canvas>
	</div>
</div>

JS

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


//日本語
//createJS047.js
//マスク分割標準 一括画像ロード
//easeljs-0.7用

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

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

//アニメ速度
var shapemask_speed=1000;//Shapeマスク速度 600-1000
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で使用
var maskSplit_free=true;//true false

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

//マスク自動分割の場合、free分割データを登録/奇数値が良い
//デモ用
var maskSplitHs=[11,11,11,11,7,11,7,11,3,1,1];
var maskSplitVs=[5,5,5,5,3,5,3,1,3,9,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;
var once=true;

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

var out_radius=30;//10-30
var in_radius=0.1;//0.5
var out_value=0;
var in_value=0;
var move_graphics=false;

var keep_speed=shapemask_speed;

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

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

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

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

	//welcome画像層画像なし
	welcomecontainer=new createjs.Container();
	stage.addChild(welcomecontainer);
	stage.update();

	//Canvas要素保存/幅、高さ、色
	keep_mainImage=createColorCanvas (canvasWidth,canvasHeight,"#FFFFFF");

	//下画像層、空画像コンテナを作る/寸法設定なくともOK
	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) {

		//progressbar遅延調整
		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();

			//待ち時間
			setTimeout(function() {
				//画像表示に進む
				draw_image();
			},wait_time);

		},500);
	}
}

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

	globalflag=false;//未使用
	//カウントクリア
	maskkcount=0;

	//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];

	//指定図形番号
	var splitNo=dataNo;
	//マスク分割変更
	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 maskflag=Math.floor(Math.random()*3);
	var color_mask=false;//カラーマスク
	if (maskflag < 2) {color_mask=true;}
	//マスク番号
	var maskNo=0;

	//Even算出
	var even_v=1;
	if (maskSplit_v % 2 != 0) {even_v=0;}
	var flag3=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 == 0) {
				//maskChip[k].graphics.beginFill().drawCircle(maskChip_W[k]/2,maskChip_H[k]/2,maskChip_W[k]/2);//円
				maskChip[k].graphics.beginFill().drawEllipse(0,0,maskChip_W[k],maskChip_H[k]);//だ円のほうが良い
				rate_v=1.5;//拡大率
				customChip=true;
				move_graphics=false;
			}
			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;
				move_graphics=false;
			}
			//可変1
			if (splitNo == 2) {
				maskChip[k].graphics.beginFill();
				operaRoundRect(maskChip[k],0,0,maskChip_W[k],maskChip_H[k],0.1);//可変角丸
				rate_v=1;//拡大率
				customChip=true;
				move_graphics=true;
				out_radius=30;
				in_radius=0.1;
				maskNo=1;
			}
			//可変2
			if (splitNo == 3) {
				maskChip[k].graphics.beginFill();
				operaRoundRect(maskChip[k],0,0,maskChip_W[k],maskChip_H[k],0.1);//可変角丸
				rate_v=1;//拡大率
				customChip=true;
				move_graphics=true;
				out_radius=15;
				in_radius=0.1;
				maskNo=1;
			}
			//可変6角
			if (splitNo == 4) {
				maskChip[k].graphics.beginFill();
				if (inType) {
					maskChip[k].graphics.beginFill();drawHexagon(maskChip[k],0,0,maskChip_W[k],maskChip_H[k]);//可変6角
				}
				if (!inType) {
					maskChip[k].graphics.beginFill().drawRect(0,0,maskChip_W[k],maskChip_H[k]);
				}
				rate_v=1;//拡大率
				customChip=true;
				move_graphics=true;
				out_value=maskChip_H[k]*0.25;
				in_value=maskChip_H[k]*0.25;
				maskNo=2;
			}
			//通常分割
			if (splitNo > 4) {
				//カラーマスク
				if (color_mask) {
					var color="#FFFFFF";
					//1
					if (maskSplit_all < 2) {color=createjs.Graphics.getHSL(Math.floor(Math.random()*24)/24*360,100,50);}//直接
					//2-
					if (maskSplit_all > 1) {
						if (maskflag == 0) {color=createjs.Graphics.getHSL(k/maskSplit_all*360,100,50);}//直接
						if (maskflag == 1 && flag3 > 0) {color="#000000";}
					}
					maskChip[k].graphics.beginFill(color).drawRect(0,0,maskChip_W[k],maskChip_H[k]);
				}
				if (!color_mask) {
					maskChip[k].graphics.beginFill().drawRect(0,0,maskChip_W[k],maskChip_H[k]);
				}
				move_graphics=false;
			}

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

	//アニメ条件設定
	//配列クリア
	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 chgflag4=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()*7);
	//delayed遅延させる/20%
	var delayed=Math.floor(Math.random()*5);

	//透明度
	var alpha_no=Math.floor(Math.random()*2);
	if (color_mask) {alpha_no=0;}//マスク着色補正

	//配置disposition位置
	var disposition_no=Math.floor(Math.random()*7);
	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;
	}

	//スライド判定
	var slide=false;
	//カスタムマスク強制透明度補正
	//if (customChip) {alpha_no=0;}

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

	//配置条件設定
	var flag3=1;
	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];
				break;
				case 1://少しずらす拡大率補正/ずれない時もある
					disposition_X=set_maskpos_X[k]+maskChip_W[k]/2*rate_v*(chgflag3-1);
					disposition_Y=set_maskpos_Y[k]+maskChip_H[k]/2*rate_v*(chgflag4-1);
				break;
				case 2://YX内部ランダム位置
					disposition_X=Math.floor(Math.random()*canvasWidth);
					disposition_Y=Math.floor(Math.random()*canvasHeight);
				case 3://中央
					disposition_X=canvasWidth/2;
					disposition_Y=canvasHeight/2;
				break;
				case 4://縦中央付近
					if (set_maskpos_X[k] >= canvasWidth/2){disposition_X=canvasWidth/2+(chgflag3-1)*100;}
					if (set_maskpos_X[k] < canvasWidth/2){disposition_X=canvasWidth/2+(chgflag4-1)*100;}
					disposition_Y=set_maskpos_Y[k];
					alpha_no=0;
				break;
				case 5://上下位置
					var c_v=chg_v;
					//交互
					if (chgflag == 1) {c_v *=flag3;}
					disposition_X=set_maskpos_X[k];
					disposition_Y=canvasHeight/2+(canvasHeight*0.6+maskChip_H[k]/2*rate_v)*c_v;
					slide=true;//スライド
				break;
				default://その場所
					disposition_X=set_maskpos_X[k];
					disposition_Y=set_maskpos_Y[k];
					alpha_no=0;
			}

			//スケール方向決定
			switch(scale_no){
				case 0:
					scale_X=0;scale_Y=0;
				break;
				case 1:
					scale_X=1;scale_Y=1;
					if (disposition_no == 1) {alpha_no=0;}//強制補正
				break;
				case 2:
					scale_X=0;scale_Y=1;
				break;
				case 3:
					scale_X=1;scale_Y=0;
				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;}

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

			//Mask-alpha
			var base_alpha=1;
			if (color_mask) {base_alpha=0;}//0

			//初期の移動
			//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=base_alpha;//0 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 (delay_no < 2) {delay_st[k]=(i+j)*delay_speed;}

			//円形状外から中心に
			if (delay_no == 2) {delay_st[k]=(Math.abs(Math.abs(i-sh/2)-sh)+Math.abs(Math.abs(j-sv/2)-sv))*2*delay_speed;}
			//対角組あわせX状に
			if (delay_no == 3) {delay_st[k]=(Math.abs(i-(sh/2))-Math.abs(j-(sv/2)))*4*delay_speed;}
			//適当なランダム
			if (delay_no == 4) {delay_st[k]=Math.floor(Math.random()*maskSplit_all)/2*delay_speed;}

			//追加、対角中より外に/対角方向違い
			if (delay_no > 4) {delay_st[k]=Math.abs(j*maskSplit_h/maskSplit_v-Math.abs(i-sh)*chg_v)*1.5*delay_speed;}

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

//テキストを表示
//set_text("分割[ "+maskSplit_h+"x"+maskSplit_v+": "+maskSplit_all+" ] / IN: "+inType+" / splitNo."+splitNo+" / dispositionNo."+disposition_no+" / delayNo."+delay_no+" / colorMask: "+color_mask);

	//速度変更
	shapemask_speed=keep_speed;
	//1枚画像、スライド速度
	if(slide || maskSplit_all == 1) {shapemask_speed *=1.25;}

	//maskされた画像の透明度を変えるか
	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;}

	//outのマスクalpha
	var out_alpha=1;

	//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_Y,rotation:0,skewX:0,skewY:0,alpha:1};
				img_st[k].alpha=alpha_no;
			}
			if (!inType) {
				//カラーマスク補正
				if (color_mask && scale_no == 1) {out_alpha=0;}
				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,alpha:out_alpha};
				img_st[k].alpha=1;
			}

			var tween=createjs.Tween.get(maskChip[k])
			.wait(delay_st[k]);
			if (maskNo == 1) {tween.call(maskchg);}
			if (maskNo == 2) {tween.call(maskchg2);}
			tween.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 () {

	var time_v=400;
	if(move_graphics) {time_v=shapemask_speed;}//長い

	//全て完了
	if(maskkcount == maskSplit_all-1) {
		//画像alpha処理調整
		setTimeout(function(){
			finshAll();
		},time_v);//可変
	}
	//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();

	//クリア
	maskkcount=0;

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

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

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

	},500);

}

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

//マスク
function maskchg (event) {

	var r=out_radius;//30
	var r2=in_radius;//0.1

	this.on('tick',function() {
		if (inType) {

			r -=(out_radius/20);
			if(r <= 0) {r=0.1;}
			if (in_radius <= r) {
				this.graphics.clear();
				this.graphics.beginFill();
				operaRoundRect(this,0,0,this.width,this.height,r);
			}
		}
		if (!inType) {

			r2 +=(out_radius/15);
			if (out_radius >= r2) {
				this.graphics.clear();
				this.graphics.beginFill();
				operaRoundRect(this,0,0,this.width,this.height,r2);
			}
		}
	});
}

//マスク2
function maskchg2 (event) {

	var m=0;
	var m2=in_value;
	var w=this.width;
	var h=this.height;

	this.on('tick',function() {
		if (inType) {

			m +=(out_value/20);
			if (out_value >= m ) {
				this.graphics.clear();
				this.graphics.beginFill();
				this.graphics.moveTo(w*0.5,0)
				.lineTo(w,h*0.25-m)
				.lineTo(w,h*0.75+m)
				.lineTo(w*0.5,h)
				.lineTo(0,h*0.75+m)
				.lineTo(0,h*0.25-m)
				.lineTo(w*0.5,0);
			}
		}
		if (!inType) {

			m2 -=(in_value/10);
			if (in_value >= m2 ) {
				this.graphics.clear();
				this.graphics.beginFill();
				this.graphics.moveTo(w*0.5,0)
				.lineTo(w,h*0.25-m2)
				.lineTo(w,h*0.75+m2)
				.lineTo(w*0.5,h)
				.lineTo(0,h*0.75+m2)
				.lineTo(0,h*0.25-m2)
				.lineTo(w*0.5,0);
			}
		}
	});
}

//Hexagon
function drawHexagon3 (s,x,y,w,h) {
	s.graphics.moveTo(w*0.5,0)
	.lineTo(w,h*0.25)
	.lineTo(w,h*0.75)
	.lineTo(w*0.5,h)
	.lineTo(0,h*0.75)
	.lineTo(0,h*0.25)
	.lineTo(w*0.5,0);
}

//次ぎの開く要素を計算
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);
}
//Hexagon
function drawHexagon (s,x,y,w,h) {
	s.graphics.moveTo(w*0.5,0)
	.lineTo(w,h*0.25)
	.lineTo(w,h*0.75)
	.lineTo(w*0.5,h)
	.lineTo(0,h*0.75)
	.lineTo(0,h*0.25)
	.lineTo(w*0.5,0);
}
//------------------------------------------------------------------------------

//色付きcanvasを作る
function createColorCanvas (w,h,c) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);
	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
init();

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


CSS

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


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

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


簡単な説明


マスクの処理方法を変える


番外編テストですのでイイカゲンなものです。マスクを着色して変化をさせるは使えるかも知れません。

 

マスク要素をシェイプトゥイーンもどきでグラフイックをカキカエ

完全なシェイプトゥイーンでは有りませんし、処理が重なる部分なので見栄えはよくない。この部分は負荷が大きくマシン性能に左右されます。例では、角丸形から角形に変化させます。


1. シェイプトゥイーンを使うかの判断は人により違うでしょう。通常よりキレイには見えません。
(将来はどうなるかはわからない、環境、CreateJSの進化次第である)
2. 簡単に tick で少々グラフイックをカキカエているだけです。キレイなシェイプトゥイーンの方法はあるが簡単に処理した。(jsdo.itに資料はあるが、実際に試してはいません)
3. 分割の大きさより、大きなマスクで透明度を与えた場合のキレイさが出なくなるのが欠点だ。
(マスクが大きいと透明度で図形が重なり偶然出来るパターンが結構キレイでアル)
4. 手間隙かければ、色々良い方法が見つかるかも知れない?
5. 6角形のマスクはラインの描画ポイントを変化させた簡単なものです。
6. マシン及びデスプレィ環境によって見え方が結構違う。出来れば状況を確認されたし。


角丸の半径を変化させる方法でゴマましている。これで円に近いものは描けるがひずんだ円である。最低の径が 0 になら無い様に注意下さい。ブラウザによりエラーになる。
この例は、createjs.Ticker.setFPS(20)の場合である。
IN OUT で少々違いがあるので注意下さい。またマシン性能違いで見え方は違う。画像のフェード処理にパワーを奪われているのが原因と思います。



角丸の大きさを設定する、in_radiusは 0 ではない

//可変1
if (splitNo == 2) {
	maskChip[k].graphics.beginFill();
	operaRoundRect(maskChip[k],0,0,maskChip_W[k],maskChip_H[k],0.1);//可変角丸
	rate_v=1;//拡大率
	customChip=true;
	move_graphics=true;
	out_radius=30;
	in_radius=0.1;
	maskNo=1;
}

--------------------------------------------------------------------------------
tick毎に角丸の大きさを変化させている、setFPS(20)時

//マスク変化
function maskchg (event) {

var r=out_radius;//30
var r2=in_radius;//0.1

	this.on('tick',function() {
		if (inType) {

			r -=(out_radius/20);
			if(r <= 0) {r=0.1;}
			if (in_radius <= r) {
				this.graphics.clear();
				this.graphics.beginFill();
				operaRoundRect(this,0,0,this.width,this.height,r);
			}
		}
		if (!inType) {

			r2 +=(out_radius/15);
			if (out_radius >= r2) {
				this.graphics.clear();
				this.graphics.beginFill();
				operaRoundRect(this,0,0,this.width,this.height,r2);
			}
		}
	});
}

● マスク変化に伴う遅延処理

デモではその都度、createjs.Ticker.addEventListener('tick',tick)を設定しています。
マスクを変化させた場合に、大きさの変更終了までの時間が必要です。下記の様に遅延させています。
遅延時間は、アニメ速度 shapemask_speed を与えています。

最終的には下画像と入れ替えになりますので、適当な時間でも差し支えはないのですが、、


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

	var time_v=400;
	if(move_graphics) {time_v=shapemask_speed;}//長い

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

条件毎にテストして、問題のある場合は修正しなければならない繁雑さが有ります。


マスクを着色して変化をさせる

通常CreateJSでは「マスク」はFlashとは違い、非表示あるいは透明化して使用します。「マスク」が自動的に非表示にならないためです。当方の他の「デモ」などでは着色しないで使用している。
この性質を利用して、マスクを着色して変化をさせるという暴挙です。利用の道はあるような気がします。


1. マスク alpha を変化させますが、マスクされた画像の alpha を変化させると、マスクが見えますから、これを組み合わせます。(虹色、または交互に白黒の2種類設定した、この辺は自由である)
2. マスクのグラデーション塗りで alpha を変化させる事も可能ですから、多少違ったものも出来るかも知れません。(手間隙かけても余りの効果は無いかも?)
3. マスクされた画像の alpha を変えない場合は、下のマスクは見えません。
4. この特性が判っていたので、マスクグラフイックは、色をあたえず、beginFill()で処理していた。
(内部処理的には、#000000、alpha=0、である)
5. 将来、CreateJSでの「マスクの仕様」が変わったりした場合は利用出来なくなります。


虹色着色、白黒交互着色、1枚画像の場合赤色。


確率の設定、3 以上にすれば、通常のマスクが増える

var maskflag=Math.floor(Math.random()*3);
var color_mask=false;//カラーマスク
if (maskflag < 2) {color_mask=true;}

//通常分割
if (splitNo > 4) {
	//カラーマスク
	if (color_mask) {
		var color="#FFFFFF";
		if (maskflag == 0) {color=createjs.Graphics.getHSL(k/maskSplit_all*360,100,50);}//直接
		if (maskflag == 1 && flag3 > 0) {color="#000000";}
		maskChip[k].graphics.beginFill(color).drawRect(0,0,maskChip_W[k],maskChip_H[k]);
	}
	if (!color_mask) {
		maskChip[k].graphics.beginFill().drawRect(0,0,maskChip_W[k],maskChip_H[k]);
	}
	move_graphics=false;
}

1枚画像の場合、画像の色を24色より着色した。


if (splitNo > 4) {
	//カラーマスク
	if (color_mask) {
		var color="#FFFFFF";
		//1
		if (maskSplit_all < 2) {color=createjs.Graphics.getHSL(Math.floor(Math.random()*24)/24*360,100,50);}//直接
		//2-
		if (maskSplit_all > 1) {
			if (maskflag == 0) {color=createjs.Graphics.getHSL(k/maskSplit_all*360,100,50);}//直接
			if (maskflag == 1 && flag3 > 0) {color="#000000";}
		}
		maskChip[k].graphics.beginFill(color).drawRect(0,0,maskChip_W[k],maskChip_H[k]);
	}
	if (!color_mask) {
		maskChip[k].graphics.beginFill().drawRect(0,0,maskChip_W[k],maskChip_H[k]);
	}
	move_graphics=false;
}

分割マスクのスケール

 

マスクの伸縮方向の設定に成りますので、殆んどの「デモ」では、変数、scale_no の値 0-3 で制御されています。
通常は問題は有りませんが、inType=false、マスク着色で scale_no=1 つまり伸縮しない状態で、その場所でTweenを実行しますと、画像フエードアウト後にマスクが残って見えてしまいます。
よって、マスクの透明度を 0 に成るように修正の必要が有ります。

それ以外の scale_no では、マスクが縮小して消滅しますので安心です。この辺は設計次第で修正したり大変面倒ですし、ランダムな条件下では気が付かない事も有ります。


● マスクの透明度を 0 に成るように修正


//outのマスクalpha
var out_alpha=1;

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

if (!inType) {
	//カラーマスク補正
	if (color_mask && scale_no == 1) {out_alpha=0;}
	params={x:mov_maskpos_X[k],.......................,alpha:out_alpha};
	img_st[k].alpha=1;
}

● 面倒な場合は常時 0 に成る様にする。但し色は常に薄く成る


if (!inType) {
	params={x:mov_maskpos_X[k],.......................,alpha:0};
	img_st[k].alpha=1;
}

条件毎にテストして、問題のある場合は修正しなければならない繁雑さが有ります。


設定状態を表示する

色々と機能などを盛り込むと、問題が発生し易くなりますので、テキスト表示を利用して状態を表示すると便利です。修正の目安になります。


//テキストを表示
//set_text("分割[ "+maskSplit_h+"x"+maskSplit_v+": "+maskSplit_all+" ] / IN: "+inType+" / splitNo."+splitNo+" / dispositionNo."+disposition_no+" / delayNo."+delay_no+" / colorMask: "+color_mask);

問題点

他のものと比較してマスク方式は問題が多い。時間の経過と共に環境は良くなるだろうとは思いますが、、、


1. マスクのTweenと画像のTweenと別にしなければなら無いので時間的な誤差が発生するし且つ重く成る。
2. これにまた別のTweenを処理するのはキツイ所でアル。(マシン性能がよければ問題は少ない)
3. 多くのマスク要素を配置出来ない。(性能のよくない環境もあるからせいぜい50-60位である)


マシン環境に拠る違い

Tween処理に大きな負荷がかかるので、マシン環境が悪いと効果の見え難いことがある。一応悪い環境で作っていますので....
マシン環境の良い方は余り問題は出ないでしょう。
つまり、対象マシンを考慮した設計をしないと負荷が増え動きが悪くなるので注意が必要である。



 

画像

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


一応、ナントカ完動しますが全てテストです。効率化のため、予告無くJSなど修正する場合がありますので了承下さい。シランフリしてマチガイ修正の暴挙も有りますので危険です!


こんな面倒な事をする人はイナイでしょう。以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]