POPSブログ

jQueryで画像分割して色々なエフェクト

195

  Category:  jquery2013/01/19 pops 

jQueryで、画像を分割 delay() で表示パターンを作り、色々なエフェクト処理を行ってみます。その都度、画像分割を変化させたりの組み合わせでエフェクトが100種類以上になります。

 

jQueryで画像分割して色々なエフェクト

jQueryで、画像を分割して、delay()を利用して表示パターンを作り、エフェクト処理を行う作業の基本は前々ページで述べた。「標準のパターン」は前ページで述べた。今回は2つを組み合わせアレンジする方法について簡単に考えて見る。分割次第では「標準のパターン」が合わない事もある。基本的に、


1. 格子状複数分割したものは「標準のパターン」を適用する。
2. その外「標準のパターン」に合わないものは、その都度パターンを作る。
3. 少し変化を多彩にするため「移動」も少し組み合わせる。
4. 同じ様に見えるものもありますが、100種以上の違ったエフェクトを得られます。(実際組み合わせは数百種)
5. このサンプルでは、規則性のある「スライド」はいれていません。


「標準のパターン」は格子状複数分割用に20種類ほどパターンを組み合わせた、汎用のパターンを言う。(一般的には名称は有りません、当方がつけたものです)


画像分割を変化して表示する(パターン使用) サンプル


注意、多少重くなりますので、マシン性能が良くない場合は、Chrome でご覧ください。


Example

エフェクト中はボタンを押しても無効です。画像をロード出来ない場合「Loading画像」を「クリック」すれば解除されます。


  • PHOTO1
  • PHOTO2
  • PHOTO3
  • PHOTO4


 

サンプルのHTML JS CSS


HTML


<ul id="tab-menu">
	<li text="/main/images/toyota_car10.jpg">PHOTO1</li>
	<li text="/main/images/toyota_car11.jpg">PHOTO2</li>
	<li text="/main/images/toyota_car12.jpg">PHOTO3</li>
	<li text="/main/images/toyota_car13.jpg">PHOTO4</li>
</ul>
<div id="image-box-base">
	<div id="image-box"><img /></div>
	<div id="top-box"></div>
	<div id="loading"></div>
	<div id="text-view"></div>
</div>

text属性は当方が勝手に作った属性です。jquery attr() で読み込みできます。

画像URLは上記サンプルの例です。使用者の画像収納先に合わせてください。右上のテキスト(#text-view)はJSで非表示にできます。


JS

slice03.js


//slice03.js
//日本語
//パターン使用

(function($){

	$(function () {

		//設定
		var select_no=0;//最初に開くメニューの位置
		var speed=600;//フェード速度 400-800
		var delay_speed = 100;//delay基準時間 50-200

		box_W=640;//画像BOX幅
		box_H=300;//画像BOX高さ

		//in outの設定は専用、autoならin_type_nmのデータで確率計算
		var in_out="auto";// in out auto
		//分割のの種類
		var split_type="free";// free set

		//free分割データ
		var splitHs=[9,9,9,9,6,4,10,7,10,3,3,13,7];
		var splitVs=[5,5,5,5,3,2,5,7,2,5,9,1,1];

		//set分割の設定、分割は固定される
		var split_h=9;//横分割数
		var split_v=5;//縦分割数
		var split_total=split_h*split_v;//分割合計
		var split_max=50;//最大分割合計

		//パターン使用、通常use
		var pattern_use="use";// use none

		//交互遅延係数
		var delayed_v=[1,1,1.5,2,2.5];

		//TEXT
		var textview_use="use";// use none

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

		var no=0;
		var keep_no=select_no;
		var img_url="";
		var load_url="";
		var keep_url;

		//chip sliceオブジェクト
		var chipboxs=[];
		//chipの位置、大きさ保存容器
		var chip_pos_X=[],chip_pos_Y=[],chip_W=[],chip_H=[];
		//スライス変数
		var slice_W=0,slice_H=0,slice_Wb=0,slice_Hb=0;

		//IN OUT、確率変更可能
		var in_type_nm=['in','out','in','out','in','out'];
		var slice_move_type="in";

		//移動ポイント配列
		var pointx=[0,box_W/2,box_W,box_W,box_W,box_W/2,0,0,box_W/2,box_W/2,box_W/2,box_W/2];
		var pointy=[0,0,0,box_H/2,box_H,box_H,box_H,box_H/2,box_H/2,box_H/2,box_H/2,box_H/2];

		var move=false;
		//移動位置配列
		var mv_posX=[];
		var mv_posY=[];
		//移動大きさ配列
		var mv_chipW=[];
		var mv_chipH=[];

		var sliceflag=0;
		var anime_move=false;
		var box_len;
		var delayflag=0;
		var patternflag=false;

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

		//外枠jqueryオブジェクト
		var tabmenu=$("#tab-menu");
		var boxbase=$("#image-box-base");
		var imagebox=$("#image-box");
		var topbox=$("#top-box");
		var loading=$("#loading");

		//欄外移動
		topbox.css({'left':box_W});
		//loadingを一旦けす
		loading.css({'display':'none'});

		//指定場所のOPEN
		tabmenu.find("li").eq(select_no).addClass("active");
		img_url=tabmenu.find("li").eq(select_no).attr('text');
		//指定画像を表示
		imagebox.children("img").attr({'src':img_url});
		//
		load_url=keep_url=img_url;

		//スライス要素作成
		init();

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

		//init スライス要素作成
		function init() {

			//スライス要素最大値
			var roop_v=split_max;
			if (split_type == 'set') {
				roop_v=split_total;
			}
			//スライス要素を作る
			//make chip
			var sliceboxs="";
			for (var i=0; i < roop_v; i++) {
				sliceboxs += '<div id="'+ 'slice'+ i + '" class="slice_bk"></div>';
			}
			//append #top-box
 			$('#top-box').append(sliceboxs);
			//len 実際に作った個数
			box_len = $('.slice_bk').length;
			//slice chips
			for (var i=0; i < roop_v; i++) {
				chipboxs[i]=$("#slice"+i);
			}

			//slice-set
			if (split_type == 'set') {
				slice_set();
			}

		}

		//スライス要素の位置大きさ決定、保存
		function slice_set() {

			//スライス
			slice_W=Math.round(box_W/split_h);//YOKO
			slice_H=Math.round(box_H/split_v);//TATE
			slice_Wb=box_W-slice_W*(split_h-1);
			slice_Hb=box_H-slice_H*(split_v-1);

			var k=0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {
					//大きさ保存
					chip_W[k]=slice_W;
					if (i == split_h-1) {chip_W[k]=slice_Wb;}
					chip_H[k]=slice_H;
					if (j == split_v-1) {chip_H[k]=slice_Hb;}
					//位置保存
					chip_pos_X[k]=slice_W*i;
					chip_pos_Y[k]=slice_H*j;

					k ++;
				}
			}
		}

		//メニューclick-action
		tabmenu.find("li").click(function() {

			//作動中は反応しない
			if(anime_move) {return false}
			no=tabmenu.find("li").index(this);
			if(no == keep_no) {return false}
			//メニューactive
			tabmenu.find("li").removeClass("active");
			$(this).addClass("active");

			//画像URL取得、画像の読み込み
			load_url=$(this).attr('text');
			imgload ();
			return false;

		});

		//loading-click-action
		loading.click(function() {
			//
			loading.css({'display':'none'});
			//menuを前に戻す
			tabmenu.find("li").removeClass("active");
			tabmenu.find("li").eq(keep_no).addClass("active");
			//フラグもどす
			anime_move = false;
			return false;
		});

		//画像Preloader
		function imgload () {

			loading.css({'display':'block'});
			//imgPreloaderを作成
			var imgPreloader=new Image();
			//イベントハンドラ
			imgPreloader.onload=function() {

				loading.css({'display':'none'});
				//画像表示に進む
				show_image();

			}
			//重要、最後に書く
			imgPreloader.src=load_url;
		}

		//画像表示処理
		function show_image() {

			anime_move=true;

			//BOX欄外移動
			topbox.css({'left':box_W,'top':0});

			//auto分割
			if (split_type == 'free') {

				//slice要素縮小
				//$(".slice_bk").css({'top':0,'left':0,'width':0,'height':0});
				//slice要素縮小
				for (var i=0; i < box_len; i++) {
					chipboxs[i].css({'top':0,'left':0,'width':0,'height':0});
				}

				splitNo=Math.floor(Math.random() * splitHs.length);
				split_h=splitHs[splitNo];
				split_v=splitVs[splitNo];
				split_total=split_h*split_v;//分割合計

				slice_set();

			}
			//IN OUT、現在IN固定
			slice_move_type=in_out;
			if (in_out == 'auto') {
				slice_move_type=in_type_nm[Math.floor(Math.random()*in_type_nm.length)];
			}

			//Even算出、分割が変わるので再計算
			even_v = 1;
			if (split_v % 2 != 0) {even_v=0;}

			//delayクリア
			var delay_st=[];
			//delayパターンクリア
			var delay_pt=[];

			//opacity用/スケール0は透明
			var optflag=Math.floor(Math.random()*4);

			//多目的判定用
			var chgxyflag=Math.floor(Math.random()*5);
			//多目的判定用2 追加
			var chgflag=Math.floor(Math.random()*2);
			//delayed遅延させる/20%
			var delayed=Math.floor(Math.random()*5);
			//標準delay_no 0-8
			var delay_no=Math.floor(Math.random()*8);

			//スケール変化
			var scale_no=Math.floor(Math.random()*2);

			//ランダムポイント移動4種、確率20%
			move=false;
			var pointflag=Math.floor(Math.random()*20);//20
			var mvpoint=Math.floor(Math.random()*12);
			//ランダムポイント移動有効、move=trueにする
			if (pointflag < 4) {move=true;}

			//パターン有効80%/0以外trueになる
			var pattern_on=Math.floor(Math.random()*5);
			var pattern_no=0;
			patternflag=false;

			//片側1分割は標準のパターンを使用しない、現在設定していない
			//if (split_h == 1 || split_v == 1) {pattern_on=0;}

			//パターン使用
			if (pattern_use == 'use' && pattern_on) {
				patternflag=true;
				//pattern-no
				pattern_no=Math.floor(Math.random()*22) || 0;
			}

			//optflag=0の場合透明度を設定する
			var opt=false;
			if (optflag < 1) {opt=true;}

			//透明はスケール0
			if(opt) {scale_no=0;}
			//スケール0 は透明
			if(scale_no == 0) {opt=true;}

			//遅延係数設定
			var d_v=delayed_v[Math.floor(Math.random()*delayed_v.length)];

			var slice_url=load_url;
			if (slice_move_type == 'out') {slice_url=keep_url;}

			//背景画像挿入
			var k = 0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

					//位置大きさCSSはあとで
					//chipboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});
					//BACKGROUND-SET url
					chipboxs[k].css({'background-image':'url('+ slice_url + ')'});
					//BACKGROUND-SET position
					chipboxs[k].css({'backgroundPosition':(chip_pos_X[k] * -1) + 'px ' + (chip_pos_Y[k] * -1) + 'px'});

					k ++;
				}
			}

			if (slice_move_type == 'out') {imagebox.children("img").attr({'src':load_url}).css({'display':'block'});}

			//初期の大きさ-SET
			var pos_sx=0;
			var pos_sy=0;
			var chipW=0;
			var chipH=0;
			var flag3=1;
			var k = 0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

					//opacityの補正
					chipboxs[k].css({'opacity':1});

					//中心補正
					if(scale_no == 1) {
					//全てその場中心補正、実際には場所をずらして中心補正をしているようにみせかけて要る
						pos_sx=chip_pos_X[k]+Math.floor(chip_W[k]/2);
						pos_sy=chip_pos_Y[k]+Math.floor(chip_H[k]/2);
						chipW=0;
						chipH=0;
					}

					//scale_no 0 中心補正無し
					if(scale_no == 0) {
						pos_sx=chip_pos_X[k];
						pos_sy=chip_pos_Y[k];
						chipW=chip_W[k];
						chipH=chip_H[k];
					}

					//移動
					if (move) {
						//ポイント移動1、全部random位置
						if (pointflag == 0) {
							var p=Math.floor(Math.random() * 9);
							pos_sx=pointx[p];
							pos_sy=pointy[p];
						}
						//ポイント移動2、左右分離
						if (pointflag == 1) {
							//X左右位置補正
							if (flag3 > 0) {pos_sx=box_W*flag3;}
							if (flag3 < 0) {pos_sx=chip_W[k]*flag3;}
							//Yそのまま
							pos_sy=chip_pos_Y[k];
						}
						//ポイント移動3、水平中央に収束
						if (pointflag == 2) {
							//Xそのまま
							pos_sx=chip_pos_X[k];
							//Y中央
							pos_sy=box_H/2;
						}
						//ポイント移動4、垂直中央に収束
						if (pointflag == 3) {
							//X中央
							pos_sx=box_W/2;
							//Yそのまま
							pos_sy=chip_pos_Y[k];
						}
					}

					//位置大きさ保存
					mv_posX[k]=pos_sx;
					mv_posY[k]=pos_sy;
					//移動大きさ保存
					mv_chipW[k]=chipW;
					mv_chipH[k]=chipH;

					//CSSの設定、inは移動させる
					if (slice_move_type == 'in') {
						chipboxs[k].css({'left':pos_sx,'top':pos_sy,'width':chipW,'height':chipH});
						//透明度設定
						if(opt) {chipboxs[k].css({'opacity':0});}
					}
					//CSSの設定、outはそのまま
					if (slice_move_type == 'out') {
						chipboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});
					}

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

			//標準パターン
			var sh=split_h-1;
			var sv=split_v-1;
			var center_no=split_total/2-1;

			if (patternflag) {
				var k=0;
				var kk=0;
				for (var i=0; i < split_h; i++) {
					for (var j=0; j < split_v; j++) {

						kk = j * split_h + i;
						switch(pattern_no){
							case 0:
								delay_pt[k]=Math.abs(i-(sh/2))+Math.abs(j-(sv/2));
							break;
							case 1:
								delay_pt[k]=k*0.2;
							break;
							case 2:
								delay_pt[k]=Math.abs(i+0.5-sh/2)+j*0.01;
							break;
							case 3:
								delay_pt[k]=Math.abs(i-j*split_h/split_v);
								//delay_pt[k]=Math.abs(i-j);
							break;
							case 4:
								delay_pt[k]=(j+i)/4+2*i;
							break;
							case 5:
								//delay_pt[k]=2;
								//対角早い
								delay_pt[k]=(i+j)*0.2;
							break;
							case 6:
								delay_pt[k]=Math.abs(sv-j)+Math.abs(sh-i);
							break;
							case 7:
								delay_pt[k]= 2+Math.abs(sh-i);
							break;
							case 8:
								delay_pt[k]=(Math.abs(Math.abs(i-sh/2)-sh)+Math.abs(Math.abs(j-sv/2)-sv))*0.75;
							break;
							case 9:
								delay_pt[k]=Math.abs(i-sh/2)+j*0.01;
							break;
							case 10:
								delay_pt[k]=(split_h*split_v-kk)/2;
							break;
							case 11:
								delay_pt[k]=kk/2;
							break;
							case 12:
								delay_pt[k]=(2+j)+(Math.abs(Math.abs(i-sh/2)-sh));
							break;
							case 13:
								delay_pt[k]=Math.floor(Math.random()*10)+1;
							break;
							case 14:
								delay_pt[k]=Math.abs(k-(split_h*split_v)/2)/2;
							break;
							case 15:
								delay_pt[k]=Math.abs(k/2-j)/2;
							break;
							case 16:
								delay_pt[k]=Math.abs(i-(sh/2))-Math.abs(j-(sv/2));
							break;
							case 17:
								delay_pt[k]=Math.abs(j*split_h/split_v-Math.abs(i-sh));
							break;
							case 18:
								delay_pt[k]=Math.abs(j+Math.abs(i-sh));
							break;
							case 19:
								delay_pt[k]=Math.abs(i+Math.abs(j-sv));
							break;
							case 20:
								delay_pt[k]=2+ Math.abs(sv-j)+(Math.abs(Math.abs(i-sh/2)-sh));
							break;
							default:
								delay_pt[k]=(i+j);
							}

						k ++;
					}
				}

			}

			//delayを設定する/delay_noで判定
			var flag3=1;
			var kk=0;//方向違いカウント
			var kkk=0;//半分でカウントダウン
			var k=0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

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

					//pattern設定なし
					if (!patternflag) {
						if (delay_no == 0) {
							delay_st[k]=(i+j)*delay_speed;
						}
						//IE対策、本来は(i+j)
						if (delay_no > 0 && delay_no < 5) {
							delay_st[k]=(i+j+k/split_total/4)*delay_speed;
						}
						if (delay_no == 5) {
							delay_st[k]=50;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 > 7 ) {
							delay_st[k]=k*delay_speed;
						}

					}
					//pattern倍速補正
					if (patternflag) {
						delay_st[k]=delay_pt[k]*2*delay_speed;
					}

					//delayed遅延/遅延係数使用
					if (delayed == 1) {
						if (flag3 < 0) {delay_st[k] +=(500*d_v);}
					}

					k ++;
					flag3 *= -1;

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

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

			//原点に戻す
			topbox.css({'left':0,'top':0});

			//TEXT
			if (textview_use == 'use') {
				var text="";
				var reverse_tx="";
				if (chgxyflag > 2) {reverse_tx=" / 反転";}
				if (patternflag) {
					text=" .SPLIT[ " + split_h + " x " + split_v + " ] / TYPE " + slice_move_type + "/ PTN " + patternflag + " / PTN-No. " + pattern_no + " SCL/ " + scale_no + " DV/ " + d_v + reverse_tx;
				} else {
					text=" .SPLIT[ " + split_h + " x " + split_v + " ] / TYPE " + slice_move_type + "/ DELAY.No " + delay_no + " SCL/ " + scale_no + " DV/ " + d_v + reverse_tx;
				}
				$("#text-view").text(text);
			}

			//アニメ実行、IN OUT 共用にして、取替え用変数
			var start_opt=1,end_opt=1;
			//スライスアニメカウント
			sliceflag=0;
			var k=0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

					//IN OUT 差し替え
					if (slice_move_type == 'in') {

						//anime
						chipboxs[k].delay(delay_st[k]).animate({'opacity':end_opt,'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]},speed,function() {
							sliceflag ++;
							//goto slice_image_parts
							if (sliceflag == split_total) {slice_image_parts();}
						});

					}
					if (slice_move_type == 'out') {

						//透明度設定
						if(opt) {end_opt=0;}
						//anime
						chipboxs[k].delay(delay_st[k]).animate({'opacity':end_opt,'left':mv_posX[k],'top':mv_posY[k],'width':mv_chipW[k],'height':mv_chipH[k]},speed,function() {
							sliceflag ++;
							//goto slice_image_parts
							if (sliceflag == split_total) {slice_image_parts();}
						});

					}

					k ++;
				}
			}

		}

		//アニメ終了処理
		function slice_image_parts() {

			setTimeout(function(){
				sliceflag=0;
				img_url=load_url;

				if (slice_move_type =='in') {
					imagebox.children("img").attr({'src':img_url}).css({'display':'block'});
				}

				topbox.css({'left':box_W,'top':0});

				anime_move=false;
				keep_no=no;
				//keep-url
				keep_url=load_url;

			},500);
		};

	});

})(jQuery);

JS名、クラス名など修正したい場合は、html js css 共に該当部分を修正ください。自由な名前で設定できます。


CSS

slice03.css


/* slice03.css 日本語 */

/* tab-menu  */
ul#tab-menu {
display:inline-block;
list-style:none;
width:100%;
height:20px;
margin:0;
padding:0;
}
#tab-menu li {
display:inline;
list-style:none;
width:60px;
height:20px;
line-height:20px;
font-size:11px;
font-weight:bold;
text-align:center;
margin-right:2px;
border-top-left-radius:5px;
border-top-right-radius:5px;
-moz-border-radius-topleft:5px;
-moz-border-radius-topright:5px;
-webkit-border-radius-top-left:5px;
-webkit-border-radius-top-right:5px;
background-color:#888888;
float:left;
cursor:pointer;/*default*/
}
#tab-menu li.active {
background-color:#EEEEEE;
}
#tab-menu li:hover {
color:#FFFFFF;
background-color:#FF1493;
}

/* image-box-base */
#image-box-base {
position:relative;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
background-color:#000000;
overflow:hidden;
}

/* image-box */
#image-box {
position:absolute;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
background-color:#000000;
}
#image-box img {
width:100%;
height:100%;
}

#top-box {
position:absolute;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
overflow:hidden;
}

#top-box .slice_bk {
position:absolute;
top:0;left:0;
background-position: 0 0;
overflow:hidden;
}

/* loading */
#image-box-base #loading {
display:block;
position:absolute;
top:0;left:0;
width:100%;height:100%;
background:url("/main/images/loading.gif") no-repeat center center;
background-color:transparent;
}

/* text */
#text-view {
position:absolute;
top:0;left:0;
font-size:12px;
color:#FF0000;
}

画像URLなどはサンプルのものです。実際環境に合わせてください。

注意、loadingは一般的によく使用されています、他のJSと競合する場合は、ID名を変えるなどの処置をして下さい。


サンプルをそのまま使用する場合


JS上部の設定をご覧ください、必要なら変更します。

1. メニューは増やすことが可能です。同じ様に記載ください。
2. CSSは画像サイズを変更ください。
3. JS上部の必要箇所を変更ください。
4. 必要なら画面サイズに合わせて分割数を変更できます。(なるべく正方形に近い方がキレイ)
5. 画像は使用者がご用意ください。Loading画像はページ下にあります。


JS上部設定の補足


//free分割データ
var splitHs=[9,9,9,9,6,4,10,7,10,3,3,13,7];
var splitVs=[5,5,5,5,3,2,5,7,2,5,9,1,1];

free分割での最大分割合計
var split_max=50;//最大分割合計

//交互遅延係数
var delayed_v=[1,1,1.5,2,2.5];

//TEXT
var textview_use="use";// use none

1. free分割データは変更可能です。同じ値を登録すれば出現確率が上がります。
2. free分割での最大分割合計は、最大の分割合計を記載、上の例では 7x7=49 のため 50 を記入。大きい値でも良いが使用されないだけ。
3. 交互遅延係数は交互遅延時間に乗ずる係数です。上の例では 1 の確率が多いようになっています。小数点含むため入力注意。
4. 要素の拡大、フェード、スライド速度は speed、出現間隔の調整は delay_speed です。
5. 赤い文字のテキストを非表示にできます。(変更確認などに便利)


サンプルの基本構造


説明図


図のように、エフェクト表示用の作業層(#top-box)を利用して、画像分割したBOX要素を append して構成します。JSは、前ページのものと比較して大きく違っています。


簡単な説明


簡単に説明しますが、スライドなどを組み合わせて実際作るとなると「大変に面倒」です。根気強くやりましょう。
この構造は「IN」「OUT」の表現が出来るようになっています。
また、JSも応用の出来る構成にしています。


説明図


分割画像が複数個あるため、ループで処理しなければならないが、作業ごとにループで処理したほうが判り易い。
特にアニメの部分は、正確な delay() を得る(実行)ためにループを独立させる必要がある。それ以前の処理のループ数などは自由である。


画像の分割の種類


画像の分割を固定するか、その都度分割を変化させるかなどは自由である。どちらでも設定で変更できるようにした。


画像の分割を固定

格子状に複数分割が基本であり、奇数値で分割したほうがキレイになるようパターンが設計されている。


分割を変更

その都度分割を変化させると、変化に富んで面白いが其の分処理が面倒になる。片方が1分割、つまりスライドに適した形の場合は「スライド」させたほうが良い。(位置を移動)
サンプルでは区別はしていない。そのために必ずパターンがあうとは限らない。そこそこ見れるだけ。


動作、形状などを分類する


単に分割して表示するには簡単ですが、規則性を持たせてスライドする、2ドア、4ドア、バーチカル、ホリゾンタル、スライス、など色々と考えると、一気に面倒になります。旨く「条件分類」して組み立てて行くことが重要になります。

簡単に次ぎのように分類、ランダムに適用してアニメさせる事にする。分割数が多いと重くなるので注意する。


中心補正

スライス要素(分割した要素)の縦横半分移動させて。拡大させるもので有り本来は移動ではあるが、「中心補正」と呼ぶことにする。Flash等の中心補正とは違うが同様の効果はでる(実際は表示範囲の拡大で画像はそのまま)。

サンプルでは、scale_no=1、そのほかは scale_no=0 として区分。下図参照


スケール設定(補正)

スライス要素の縦横の大きさを変化させることに拠り、エフェクトを表現する。位置も旨く変えれば規則性のある動きになる。これらは設計段階にどのようにするか個人的な考えである。アニメ開始で大きさが0であれば拡大する。
図解すれば下記の様な分類になる。

例えば、図のように「拡大の方向」などで分類しておけば良い訳です。(0番、2番は同じでもよいと思うが、区別すれば判別し易い、このサンプルでは0番1番の区分を使用、判別の目安としている)


※ 但し、どれも透過処理は出来る。(サンプルでは、0番を透過にしている、キレイだから)
※ 図で、3番4番はスライドの代用としても使用可能。(シャッター)
※ 本来のスライドは、画面の外に移動させておき、アニメで戻すのが良い。

分類、名前、番号など、これらは設計者の自由である。判定しやすく応用の利くようにすれば良い。


透過設定(補正)

スライス要素の透明度を変化させる。動作が重くなる欠点がある。またIEではアルファフィルターのバグが発生することがある。

サンプルでは、透過の場合、opt=true、としてスライス要素の中心補正も解除している。


移動設定(スライド)

アニメ開始位置を大きく違わせることにより、スライドなどを表現する。バラバラな位置を与えても面白い。移動大きさの変化は比較的動作が軽い。スケール設定と組み合わせると面白い表現も可能。

サンプルでは、move=true、として pointflag の番号により処理している。


大きさを変化させない場合

分割画像はそのままの状態であるから、最低は「透明度」を変化させるほか選択肢は無い。回転は出来ない。
そのままでは、パッと画像が変わるだけで分割の意味が無くなる。

ここが一番のネックだ!。交互に時間差を付ける。ランダムに表示させるなどの方法はあるが。


分類の名称などは無いので、設計者が勝手に名前をつけて、動作を考慮しながら組み合わせて行く他手立ては無い。エフェクトが合わない場合もあるので如何に「ゴマカス」かが重要だ。
通常は、ランダムに設定してアニメさせるが、合わない場合の修正が大変なだけで「キニシナイ」性格なら処理は簡単、ホットケば良い。


表示パターンを決定する


格子状複数分割用に「標準のパターン」を

最初から出来上がっているので簡単に適用できる。但し合わない場合もある。

サンプルでは、patternflag=true、80% の割合で「標準のパターン」を使用するよう設定している。
残り、20% 及び、「標準のパターン」不使用の指示であれば、与えられた delay_no により個別のパターンで処理される。ここはパターンを作る他無い。



パターン使用 pattern_use の判定も行っている

//パターン有効80%/0以外trueになる
var pattern_on=Math.floor(Math.random()*5);
var pattern_no=0;
patternflag=false;

//パターン使用
if (pattern_use == 'use' && pattern_on) {
	patternflag=true;
	//pattern-no
	pattern_no=Math.floor(Math.random()*22) || 0;
}

もし、スライド形のものに「標準のパターン」を使用しない場合は判定を加えればよい。


//パターン有効80%/0以外trueになる
var pattern_on=Math.floor(Math.random()*5);
var pattern_no=0;
patternflag=false;

//片側1分割は標準のパターンを使用しない
if (split_h == 1 || split_v == 1) {pattern_on=0;}

その外、必要なら判定を加えればよい。pattern_on=0、であれば「標準のパターン」は適用されない。


個別のパターンを作る

合わない場合は処理に応じたパターンを作り適用する。

サンプルでは「標準のパターン」を使用しない場合 patternflag=true、として delay_no で個別のパターン処理。


さらに時間差をつける

条件に応じてさらに時間差をつけて、遅延させるなどでアレンジする。時間差も変化できればパターンも若干変化する(遅延係数設定)。

サンプルでは、delayed=1、の場合「交互遅延」するようにしている。


パターンの実行

アニメで delay() を実行することですが、アニメ途中で停止できませんので注意ください(stop()させると画面が乱れる)。必ず全て実行させます。そのために「アニメ中」はボタンが機能しないようになっています。

サンプルでは、画像表示処理に入ったら、anime_move=true、を与え判定しています。
アニメも複数の分割画像要素「スライス要素」をアニメしていますので、全てのアニメ終了を sliceflag のカウントで判定しています。

重要、タイマーなどを利用して「スライドショウ」化する場合も、アニメ途中で停止させないように処理します。


ランダムな変数を利用

変化させるには、ランダムな変数を発生させて、旨くこれを利用して設計する。

簡単に色々な組み合わせを作れます。出来たエフェクトが見栄えよければ問題ないが、個別に確認する手間隙が大変ですから「一長一短」あります。


確認

パターンなど少ない場合は簡単ですが、新規に作るまたは改造した時は、確認のために数値を書き込み動作を確認するなどの作業が大変です。現在の状況がわかる様テキストで表示するのも方法と思う。



例としてdelay_noの場合ランダムな数値を与えている

//標準delay_no 0-8
var delay_no=Math.floor(Math.random()*8);

実際に変数を書き込み、1つ1つ確認してゆく
delay_no=0;

色々な条件を変えながら確認する。ブラウザ違いも確認する。パターンがそれだけの効果があるかも確認。問題が有れば修正してまた確認。
チットモ前に進まん!。大抵はここで嫌になる、、、。


実際には、個人で考えてアニメさせ、実作業を繰り返して覚える外方法は無い。さらに効率的な独自の方法を確立すればよい。ハゲミナハレヤ!


その他


IN OUT でのCSS設定のタイミング

上記サンプルでは最初に、背景画像挿入時点で、「位置大きさ」をCSSで確定して「IN」の場合にまた移動している。それで背景画像挿入時点では背景のCSSのみ確定してあとで「位置大きさ」を決めても問題はなさそうである。



背景画像挿入で位置大きさを決めない

//背景画像挿入
var k = 0;
for (var i=0; i < split_h; i++) {
	for (var j=0; j < split_v; j++) {
		//位置大きさ
		//chipboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});

		他略す

		k ++;
	}
}

初期の大きさ-SETで位置大きさを決める

//CSSの設定、inは移動させる
if (slice_move_type == 'in') {
	chipboxs[k].css({'left':pos_sx,'top':pos_sy,'width':chipW,'height':chipH});
	//透明度設定
	if(opt) {chipboxs[k].css({'opacity':0});}
}
//CSSの設定、outはそのまま
if (slice_move_type == 'out') {
	chipboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});
}

これで動作が軽くなったと感じられるものでは無いが、、少し効率的?。


状況の表示

設定状況など、テキストで表示するようにしています。書き換え変更などの際に便利です。いらない場合は、非表示にも出来ますが、削除しても結構です。
色々な形態でのエフェクトを決定するに、条件分岐を多用しますので、変数など確認しながら作りこむ時に重要な手助けになります。



HTML
<div id="text-view"></div>

JS
//TEXT使用
textview_use="use";// use none

//textview
if (textview_use == 'use') {
	text="必要な情報が表示できるようにテキストを書く";
	$("#text-view").text(text);
}

スライス要素のクリアについて

その都度、分割を変える場合、スライス要素のチップは使い回しになりますので、一旦見えなくする処理を行います。クラスになっていますので記述は簡単ですが遅い場合はループを使用すると早い。
どちらも同じ処理ですが、ループでID名を使用したほうが早い。


クラスで処理は遅い

//slice要素縮小
//$(".slice_bk").css({'top':0,'left':0,'width':0,'height':0});

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

ID名を使用したほうが早い、こちら使用

//slice要素縮小
for (var i=0; i < box_len; i++) {
	chipboxs[i].css({'top':0,'left':0,'width':0,'height':0});
}

終了処理の setTimeout について

Firefox対策である。マシン環境が悪いFirefoxで(環境が悪くてFirefoxを使用することは常識的には無いはずだ)、画像のすり替え処理でタイミングが合わなくなる場合に有効である。従来は setTimeout は無いので削除しても良い。


異常に手間隙がかかります

エフェクトを増やすと、主に確認作業ですが途中で嫌になるほど面倒です。当然手間隙もかかります。工夫するほか方法はありません。
そんな時には「イイカゲン」に作りましょう。また旨く行かない部分をいかに「ゴマカス」かがポイントです。


将来的にはCSS3の回転など加えれば、よりFlashに近くなるでショウ。


Loading画像など

使用画像は原則、使用者がご用意ください。Loading画像は好きなものが使用可能です。

loading.gif 31x31 :




「標準のパターン」を使用する場合の解説などの記事。

【参考】当方の記事: jQueryで画像分割表示のパターンを作る


「標準のパターン」を使用しない場合の記事。

【参考】当方の記事: jQueryで画像分割を変化して表示する


以上です。

 


[ この記事のURL ]


タグ:jquery , photo , memo , slice

 

ブログ記事一覧

年別アーカイブ一覧



[1]