POPSブログ

jQuery CSS3 transit.js使用の画像分割アニメーション

362

  Category:  jquery2015/07/27 pops 

jQueryプラグイン、jquery.transit.js、で簡単にCSS3 transitionの記述が出来ますので画像分割アニメーションに応用してみました。回転も簡単に出来て便利、通常のjQueryアニメーションより軽快に動作します。ほとんどflash AS3などと同様な処理がJSのみで可能です。

 

jQuery CSS3 transit.js使用の画像分割アニメーション、テスト


jquery.transit.js、jQueryプラグインで簡単にCSS3 transitionの記述が、カスタムアニメーション animate() ライクに書けますので、通常の画像を回転させたり拡大させたりと便利です。通常のjQueryアニメーションより軽快に動作します。

以前はCSS3未対応のブラウザも多かったが、現在はセキュリティの観点から「モダンブラウザ」にほぼ移行して来ましたので、CSS3 transitionで処理してみます。

 

zu

 

ご注意、IE10以上のモダンブラウザでご覧ください(Chrome推奨)。IE9およびそれ以前のブラウザではご覧になれません。
但し、Android系の動作は不明です。


説明用画像分割アニメーション

これは、説明用の「画像分割アニメーション」で簡略化しています。
(このページではjquery-1.6.4とjquery.transit.jsを使用)

 

 

このテスト表示を見ても、CSS3 transition によって従来より早く軽く処理されているのが判ります。

 

1. 回転が簡単に出来るのが最大の利点。(scale等も使用可能)
2. 3D等も可能です。(ブラウザの機能によって多少違いあり)
3. 以前のjQuery animate()処理と比較して格段に軽い。(全てでは無いが...)
4. 軽いのでアニメーション時間も長く出来、Easingの指定も容易です。
5. 現在、transit.js対応はAndroid系が含まれていませんので動作は不明です。


z-index変更の別方法を2つ追加しました。「デモ4. 5. 参照」2015/09/06. 18 追加

 

DEMO2 画像分割アニメーション2

● デモページは [ jqury-1.9 ] で動作しています。JS、CSS、は「デモ」ページに掲載しています。


DEMO2、簡略していないJS、(一括z-index処理)

比較して、スライドなどの移動条件を多くしていますので、エフェクト数が多い。slice-transition-1.js
DEMO4. 5は z-index処理 が違うのみで、DEMO2とまったく同じエフェクト、動作です。

DEMO-021


DEMO3、簡略していないJS (skew処理の追加、一括z-index処理)

上記デモ2のJS、slice-transition-1.jsにskew処理を追加したものです。slice-transition-2.js

DEMO-021b




DEMO4、z-index処理をかえたもの2。2015/09/06 追加

上記デモ2のJS、slice-transition-1.js のz-index処理をdelay直後に行う様に修正したものです。

DEMO-021d


DEMO5、z-index処理をかえたもの3。2015/09/18 追加

上記デモ2のJS、slice-transition-1.js のz-index処理をdelay直後にqueue()を利用して行う様に修正したものです。

DEMO-021e




 

簡単な説明


CSS3 transition画像分割アニメーションの説明


「画像分割アニメーション」の部分はjQueryプラグイン、jquery.transit.jsを利用してCSS3 transition処理をしています。JS詳細は「前ページ」の記事を参照ください。

【参照】当方の記事: jQuery transit.jsの使用方法を調べてみました


「前ページ」において過度に色々なHTML構成での動作確認をしているのは、この「画像分割アニメーション」に応用した時に問題が出ないか事前に確認しておきたかった為です。
Flash等と同様な処理を行えますが、やはりHTMLでの構成上の違いが有りますのでそれを修正しながら「アニメーション」させます。コツさえつかめば面倒でもない...


1. 画像はDIV要素に背景画像として取り込み、一度positionで多数の分割画像を配置します。(固定で動かしません)
2. 動かすには「CSS3 transition」で処理します。
3. 画像の拡大はscaleで行いますので、従来の様に縦横のanimate()は行いません。
4. 回転はrotateで行います。
5. 3D処理なども可能ですが、ここでは x y 位置の移動と回転のみにします。


画像処理の上層と下層

画像処理には上層と下層の2層を準備して行います。上層で「アニメーション」して終了後、下層に画像を移し上層を消します。


1. 上層には分割画像を配置して.transitionします。
(positionで配置しますが、animate()では動かしません)
2. 分割画像はDIV要素に背景画像として取り込みますが、IDを付加して先に上層にappend()します。
(jqueryのため、appendしなければDIV要素として認識しません)
3. transitionで動かすために、自動的に回転の中心が画像の中央になります。
(実際の位置とはずれていますので、これを考慮して移動します)
4. このデモでは行っていませんが、「アニメーション」の途中でstop()は出来ませんので、「アニメーション」が完全に終了してからstop()させます。
(大変見苦しいので「アニメーション」の途中で中断するアクションは受け付けない様処理する必要があります)


画像の分割数について

縦横の分割数を登録すれば、適正に分割します。画像はピクセル単位のために整数値になるようにします。
奇数値で分割するするほうがスライドなどで綺麗になり易い様になっています。


1. 分割数によっては幅高さが必ず等分になるとは限りません。
2. 比較的、多分割に成れば誤差が大きくなります。(注意してみないと気がつかない)
3. 分割総数は動作が軽くなった分、以前より大きくとれますが、環境に応じて決定ください。
(当方としては総数を断言できないので、マシン環境など考慮して使用者が決定ください)
4. 正方形に近いほど綺麗になりますが、一応分割は自由です。
5. このデモは正方形分割が綺麗になるように、条件 エフェクト設定しています。
6. 自由に設定できますが、必ずエフェクトなどが旨く合致するとは限らない。(それなり)
7. 同じ分割が多いと出現確率が高い。



//自動分割の場合、free分割データを登録/奇数値が良い
var splitHs=[13,11,11,9,7];
var splitVs=[7,5,5,5,3];

背景画像の取り込みと配置

説明図

zuzu

 

分割の条件により、画像位置が決定されます。背景画像をDIV要素に配置するには -1 を乗算すれば決まります。

positionで配置したものを再度動かすと、transition()処理が壊れますので、最初に位置決めして後はそのままにしておく事が重要です。仮に動かさなければ成らない場合はラップして2重構造にすれば良い。



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

		//DIVの位置と大きさ
		transboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});
		//背景画像セット
		transboxs[k].css({'width':chip_W[k],'height':chip_H[k],'background-image':'url('+ slice_url + ')'});
		//BACKGROUND-SET position
		transboxs[k].css({'backgroundPosition':(chip_pos_X[k] * -1) + 'px ' + (chip_pos_Y[k] * -1) + 'px'});

		k++;
	}
}

画像の分割と配置

画像の大きさはピクセル単位ですから、必ず整数値で分割して、整数値の position left topで上層にappend()します。
(整数値でない場合は画像を並べた場合に隙がでますので、重要です)
transition移動の場合はtranslateが整数値でなくとも問題有りません。それなりの場所に描画されます。


左右、上下の移動

CSS3 transition()処理以前はposition left top で移動していましたが、
transition()処理の場合は translate x y で動かします、分割された画像の中央が 0 0 に成りますから、実際の画像位置とは異なります。(画像、幅高さの半分ずれる)

その差を考慮した、x y 値で移動させます。同じオブジェクトに jqueryのanimate() left topでは動かさないでください。


画像の大きさはscaleで処理します

jqueryでは幅と高さでしたがtransition()処理では scaleX scaleX で制御しますので、有る程度変化のパターンを決めておき規則に従い動かします。ここでは以下の様に規定します。

zu-zu-zu

 

1番の場合、欄外に移動するか、同じ位置または欄内であれば透明度を0にする必要があります。
また、回転させる場合は見苦しくない様に処理する必要があります。
つまり色々な条件で処理を修正しながら適性な「アニメーション」になる様にします。



//スケール方向決定
switch(scale_no){
	case 0:
		scale_X=0;scale_Y=0;
	break;
	case 1:
		scale_X=1;scale_Y=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;
}

INとOUT

INとOUTに区分して処理を行っています。1つの計算で2つの違った動きに成ります。単純にエフェクトを増やす手段といえます。

1. IN、はベースの外側より内側に移動、スケール0から1に、透明度0から1に、変化する事を規定します。
2. OUT、反対の動作です。
3. 一番最初はINに成ります。但し最初に「完全読み込み済み画像」があればOUTも可能です。

アニメーション処理を1つに纏める事も可能ですが、IN OUT 個別に処理しています。


delayパターン

色々な形で出現しますが、遅延時間を変える事により実現しています、仮に「delayパターン」と呼ぶことにします。
この計算式は有りませんので、個人が工夫して作る必要があります。
delay配列を反転(reverse)すればパターンも逆になりますが、全てそうなるとは限りません。
計算方法によっては、アニメの開始時間がずれたりもしますし、実行時間はマチマチです。



delay_speedの値は変更できます

//斜め位はどこでも利用している、この他は作る
delay_st[k]=(i+j)*delay_speed;

● delayの処理
delayはjqueryのdelay()、またはtransit.jsのtransition()で処理できますが、delay()の方がアニメーションがスムーズのような気がする(気のせいかナ...)


//jqueryのdelay()の処理
transboxs[k].delay(delay_st[k]).transition({translate:[0,0],rotate:0,scale:[1,1],'opacity':1},...

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

transit.jsの処理
transboxs[k].transition({delay:delay_st[k],translate:[0,0],rotate:0,scale:[1,1],'opacity':1},...

重なり順序の変更

本来ならば全ての条件設定ができてからappendすれば良いのだが、背景画像を入れるために初期状態でappendしています。
delayしている事もあり重なり順序の変更が思うように行きませんでした、試行錯誤の結果、遅延順で z-index を一括再設定しています。
並べ替え処理に幾分時間を要しますので、その後の処理を setTimeout で遅延しました。

注意、重なり順序の変更の場合、他の構造にも z-index 設定が必要です。(CSS参照)


モット簡単な方法はないでショウか...

別の方法2を、次「 重なり順序の変更2 」に追加するが、効率的には変わりなさそうで有る。2015/09/06 追加
別の方法3を、次「 重なり順序の変更3 」に追加するが、一番効率的かも知れない。2015/09/18 追加


● z-index一括変更例
transition()が1回で終結しているので、デモのような画像分割には返って「好都合」と思いますが.... どうでしょうか。


//配列
var number=[];
for (var i=0; i < split_total; i++) {
	number[i]={'id':i,'delay':Math.floor(delay_st[i])};
}
//配列をソート/delayの昇順にsort
number.sort(function(a,b) {
	var x=a.delay;
	var y=b.delay;
	if(inType){return x > y ? 1 : -1;}//IN昇順
	if(!inType){return x < y ? 1 : -1;}//OUT降順
});

for (var i=0; i < split_total; i++) {
	var dno=number[i].id;
	//ラップ無し
	transboxs[dno].css({'z-index':i});
}

//並び替えに時間がかかるので調整
setTimeout(function() {

	略す

},800);//500-1000

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

結果は同じです
css({'zIndex':i});

重なり順序の変更2

個々の画像のdelay()直後、transition()実行前、z-index 設定して常に上に来るようにしたいのですが、通常はコールバックが最後なので出来ない。
ダミーで旨く構成すればナントカ可能ではあるが...


1. 所が、transit.jsでdelayのみ単独で実行出来るので、このコールバックを利用する。
2. 無名関数で実行するので、受け渡し配列の認識のため工夫する。
3. 個々の画像は、新たに生成しているので z-index:0 の状態である。
4. delay後、順次に個々の画像に、z-index値を加算して上に重ねれば良い事になる。
(同じ、z-index値でも理論上は並びますが、delayで出現順序が違うため現実には意味がない)


効率など違いがなさそうであるが、transition()処理をネストする場合は都合が良いと思います。


transit.jsでdelayのみ単独で実行出来る。つまり下記コード、ダミーのtransition()を実行出来る。
よって、直後にz-indexを変更して、本来のtransition()をネストすれば良い。


//最初delayのみ実行
transboxs[k].transition({delay:delay_st[k]},1,function(){

	//重ねを一番上にする
	$(this).css({'zIndex':値});

	//本来のtransition実行
	$(this).transition({.......},600,function(){

		//
	});
});

無名関数で実行の受け渡し配列の認識のため、事前に個々の番号をいれておく。


for (var i=0; i < split_total; i++) {
	transboxs[i]=$("#slice"+i);//オブジェクト保存
	transboxs[i].attr('no',i);//新規chip番号取得用
}

番号を取得して、配列のデータを使用する
ループ処理ですが、i 値が受け渡しなりませんので、以下の様にします。


var no=$(this).attr('no');//番号
$(this).transition({translate:[mov_pos_X[no],mov_pos_Y[no]],....

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

attrでは無くセレクタを引数指定でindex番号を取得する時は

var no=$(this).index('.slice_text');

同じ結果ですが利用していません

明示的に個々の画像のz-indexを0にするには次を実行すれば良いが、新たに生成しているので z-index:0 の状態である
してもシナクトモ、結果は同じである。仮に画像を削除せず使いまわしの場合は初期化になる。


//z-index 0
for (var i=0; i < split_total; i++) {
	transboxs[i].css({'zIndex':0});//0
}

IN OUTで次の様になる。この例のINでは番号取得は不要で有る。中のtransition()の書き方次第では必要になる。
変数sliceflagはカウントで、0 1 2 3....と順次加算されるので利用した。

全ての分割画像の、z-index値は 0 であるから、1 より大きい値ならば上にくる。

個々の画像は直ぐに破棄するので、z-indexを0に戻す操作は行っていない。


● デモでの記載部分


if (inType) {
	//delayのみ実行0に戻さない
	transboxs[k].transition({delay:delay_st[k]},1,function(){
		//出現順に上にする/ラップなし
		$(this).css({'zIndex':1+sliceflag});
		var no=$(this).attr('no');//番号
		$(this).transition({translate:[0,0],rotate:0,scale:[1,1],'opacity':1},speed,"ease",function(){
			sliceflag ++;
			//終了
			if (sliceflag == split_total) {finshAll();}
		});
	});
}
if (!inType) {
	//delayのみ実行0に戻さない
	transboxs[k].transition({delay:delay_st[k]},1,function(){
		//出現順に上にする/ラップなし
		$(this).css({'zIndex':1+sliceflag});
		var no=$(this).attr('no');//番号
		$(this).transition({translate:[mov_pos_X[no],mov_pos_Y[no]],rotate:rotate_v[no],scale:[scale_X,scale_Y],'opacity':alpha_no},speed,"ease",function(){
			sliceflag ++;
			//終了
			if (sliceflag == split_total) {finshAll();}
		});
	});
}

無名関数で実行の受け渡し配列の認識のため、事前に個々の番号をいれておく。


for (var i=0; i < split_total; i++) {
	transboxs[i]=$("#slice"+i);//オブジェクト保存
	transboxs[i].attr('no',i);//新規chip番号取得用
}

上記「重なり順序の変更2」のデモおよびJSは下記に有ります。

[ DEMO4、重なり順序の変更2のデモ ]


重なり順序の変更3

正式な方法ではなく、queue()を騙して実行させる方法です。先日、同じ処理スタイルのテキストアニメーションのz-index変更を調べて行く過程で見つけたものです。


1. 上記の「重なり順序の変更2」をqueue()を利用して改良したものです。
2. queue関数中の処理方法は「重なり順序の変更2」と同じです。
3. 最初、transition()を実行しないで関数のみの実行ですから、多少効率が良いかも知れません。
(断言は出来ませんが...)
4. 言い方を変えれば、setTimeout()の代用にも利用できる。


使用目的によって、z-index変更が頻繁な場合、transition()処理をネストする時は都合が良いと思います。


下記jqueryのコードで、delay直後に関数を実行出来ますので、その中に記載します。
queue()実行後戻るために、必ず最後に、dequeue()、queue削除を記載します。
ループ処理で、iが使用出来ないのは、上の「重なり順序の変更2」と同じ。transition()が delay().queue() に変わっただけですから、中の処理は一応注意が必要になります。

当然、私に考えられることでは有りません。下記記事を参考に処理しました。(助かった...)

【参考】github.comの記事 : jQuery で5秒後とかに addClass したいとき


書式
オブジェクトが必ずしもanimate()シナクトモ、下記の様に実行出来ると言う事です。
つまり、アニメーションのqueueを実行する訳では有りませんので、裏技に成ると思います。(寝技かも知れない...)


オブジェクト.delay(値).queue(function(){

	//アニメ以外の処理
	$(this).....
	//queue削除で戻る
	$(this).dequeue();

});

z-index変更記載例
重なり順序の変更2は、最初、


アニメを実行している
transboxs[k].transition({delay:delay_st[k]},1,function(){

アニメ実行では無く次のqueueを実行する、内部は同じ記述です。
(queue()の中はqueueに見えるが、実際はqueueでは無い、欺いているだけ)


transboxs[k].delay(delay_st[k]).queue(function(){

	//重ねを一番上にする
	$(this).css({'zIndex':値});

	//本来のtransition実行
	$(this).transition({.......},600,function(){

		//
	});

	//queue削除
	$(this).dequeue();

});

● デモでの記載部分


if (inType) {

	//queue実行
	transboxs[k].delay(delay_st[k]).queue(function(){

		//出現順に上にする/ラップなし
		$(this).css({'zIndex':1+sliceflag});
		//var no=$(this).attr('no');//番号

		$(this).transition({translate:[0,0],rotate:0,scale:[1,1],'opacity':1},speed,"ease",function(){
			sliceflag ++;
			//終了
			if (sliceflag == split_total) {finshAll();}
		});

		$(this).dequeue();//queue削除
	});

}
if (!inType) {

	//queue実行
	transboxs[k].delay(delay_st[k]).queue(function(){

		//出現順に上にする/ラップなし
		$(this).css({'zIndex':1+sliceflag});

		var no=$(this).index('.slice_bk');
		//var no=$(this).attr('no');//番号

		$(this).transition({translate:[mov_pos_X[no],mov_pos_Y[no]],rotate:rotate_v[no],scale:[scale_X,scale_Y],'opacity':alpha_no},speed,"ease",function(){
			sliceflag ++;
			//終了
			if (sliceflag == split_total) {finshAll();}
		});

		$(this).dequeue();//queue削除
	});
}

無名関数で実行の受け渡し配列の認識のため、事前に個々の番号をいれておく。


for (var i=0; i < split_total; i++) {
	transboxs[i]=$("#slice"+i);//オブジェクト保存
	transboxs[i].attr('no',i);//新規chip番号取得用
}

上記「重なり順序の変更3」のデモおよびJSは下記に有ります。

[ DEMO5、重なり順序の変更3のデモ ]


 

回転

回転角度は原則自由ですが、問題は外側に移動した時などに「画面内部に回転した画像」が残って見苦しい事です。
スケール0、透明度0、で見えなくするなど、この処理が完全ならばどのような回転も自由です。

transition処理は結構軽く回転します。余り回っても何ですから、結構控えめに回転させています。

回転以外の処理も可能です。(skewは比較的簡単に追加できる、デモ3参照)



0を増やせば回転しない
//回転データ、余り回転しない
var rotates=[0,0,0,0,1,2,3];

実際の計算、chg_v は1か-1の値です
//rotation値の決定 90度x、逆転有り
rotate_v[k]=rotate*90*chg_v;

skew処理したJS(slice-transition-2.js)をデモ3に追加しました。2015/07/28


画像の一括ロード

画像は「一括ロード」方式で読み込みます。読み込みに失敗すれば表示数は減ります。(通常はサーバーに問題がなければ読み込むでショウ)
その所を考慮して画像数を決定ください。(書き換えればその都度1枚ずつ読み込みにも改造は出来ます)


JSでのCSS処理

下記はCSSで角丸、陰影処理したものであるが、ベンダープレフィックス無しで記載できるので便利である。



//角丸、陰影
$('#image-box-base').css({borderRadius:'10px',boxShadow:'0 0 10px #000'});

画像分割アニメーションは面倒です

簡単に作るならさほどでも有りませんが、作りこめば結構大変です。
ランダムに条件を変えているのが最大の要因ですが、間違いに気がつき難い面があります。
ほとんどは確認作業になりますが、完成までには根気がいります。数ヶ月後に間違いに気づく事もありますから、こんな時は知らんフリするか笑ってゴマカス。
設定変更はJS上部を参照ください。


 

jQuery Transitプラグイン、jquery.transit.js

JSは配布元または、githubから取得できます。各ページに説明などの記載が有りますので読まれるのが良いでしょう。


● 配布元、Web Site: Transit / jquery.transit.min.jsダウンロード可

● githubでのJSのダウンロード : jQuery Transit / jquery.transit.jsダウンロード可

 

上記デモのHTML JS CSS

transition処理には jquery.js の他に jquery.transit.js が必要です。

HTML

 


<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>

JS

slice-transition-st.js


//slice-transition-st.js
//説明用の簡略形
//標準、ラップしない1枚DIV形式、一応機能する
//z-index変更、各階層もz-indexをつけた

(function($){

	$(function () {

		//角丸、陰影必要でないなら削除する
		$('#image-box-base').css({borderRadius:'10px',boxShadow:'0 0 10px #000'});

		//初期設定
		//-----------------------------------------------------

		var split_free=true;//自動分割 true false
		var speed=800;//拡大移動、アニメ速度
		var delay_speed=120;//出現間隔、delay基準時間 100-200

		//自動分割でない場合の分割
		var split_h=11;//標準の横方向分割数、奇数値
		var split_v=5;//標準の縦方向分割数、奇数値
		var split_total;

		//読み込み画像の大きさ、未使用
		var imageH=640;
		var imageW=300;

		//baseの大きさ/全てこの値を使用
		var box_W=640;//画像BOX幅
		var box_H=300;//画像BOX高さ

		//タイマーの使用、useであること
		var timer_use="use";
		//タイマー値 5000-10000
		var time=5000;

		//テキスト表示の使用 use=true
		text_use=true;//true false

		//自動分割の場合、free分割データを登録/奇数値が良い
		var splitHs=[13,11,11,9,7];
		var splitVs=[7,5,5,5,3];

		//スケール方向番号データ 0-3
		var scales=[0,0,1,1,2,3];
		//回転データ、余り回転しない
		var rotates=[0,0,0,0,1,2,3];

		//画像リスト
		var loadImage_len=0;
		var imagelist=[
			"/main/images/flight01.jpg",
			"/main/images/flight02.jpg",
			"/main/images/flight03.jpg",
			"/main/images/flight04.jpg",
			"/main/images/flight05.jpg",
			"/main/images/flight06.jpg"
		];
		loadImage_len=imagelist.length;

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

		//読み込み画像URL保存容器
		var assets=[];
		//分割大きさ位置保存容器
		var chip_W=[],chip_H=[],chip_pos_X=[],chip_pos_Y=[];
		//実際配置位置
		var set_pos_X=[],set_pos_Y=[];
		//移動配置位置
		var mov_pos_X=[],mov_pos_Y=[];

		//変数
		var globalflag=false,timerID=null;
		var inType=true;
		var moveType="";
		var once=true;
		var viewtext;
		var sliceflag=0;
		var keep_url;

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

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

		//外枠jqueryオブジェクト
		var tabmenu=$("#tab-menu");
		var boxbase=$("#image-box-base");
		var imagebox=$("#image-box");
		var topbox=$("#top-box");
		var loading=$("#loading");
		var textview=$('#text-view');
		//欄外移動
		topbox.css({'left':box_W});
		//loadingを一旦けす
		loading.css({'display':'none'});
		//スタート
		init();

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

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

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

		}

		//DRAW、アニメ
		function imagedraw() {

			globalflag=false;
			//カウントクリア
			sliceflag=0;
			//TEXT
			text_set("");

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

			//最初はIN
			if(once){
				once=false;
				inType=true;
			}

			//分割変更
			if (split_free) {
				var splitNo=Math.floor(Math.random()*splitHs.length);
				//分割値代入
				split_h=splitHs[splitNo];
				split_v=splitVs[splitNo];
			}
			split_total=split_h*split_v;

			//スライスオブジェクトを作る
			var chipboxs=[];//ラップ未使用
			var transboxs=[];//ラップ無し
			//計算上の仮想ポイント
			var virtual_X=[];
			var virtual_Y=[];

			//make chip
			var sliceboxs="";
			for (var i=0; i < split_total; i++) {
				sliceboxs += '<div id="'+ 'slice'+ i + '" class="slice_bk"></div>';
			}
			//append #top-box
 			$('#top-box').append(sliceboxs);

			for (var i=0; i < split_total; i++) {
				transboxs[i]=$("#slice"+i);//オブジェクト保存

			}

			//スライス寸法データを得る1
			slice_set(box_W,box_H,split_h,split_v);
			//分割合計要素数計算
			split_total=split_h*split_v;

			//背景画像挿入
			var slice_url=assets[image_no];
			if (!inType) {slice_url=keep_url;}

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

					//DIVの位置と大きさ
					transboxs[k].css({'left':chip_pos_X[k],'top':chip_pos_Y[k],'width':chip_W[k],'height':chip_H[k]});
					//背景画像セット
					transboxs[k].css({'width':chip_W[k],'height':chip_H[k],'background-image':'url('+ slice_url + ')'});
					//BACKGROUND-SET position
					transboxs[k].css({'backgroundPosition':(chip_pos_X[k] * -1) + 'px ' + (chip_pos_Y[k] * -1) + 'px'});

					k++;
				}
			}

			//out
			if (!inType) {imagebox.children("img").attr({'src':assets[image_no]}).css({'display':'block'});}

			//アニメ条件設定
			//配列クリア
			var delay_st=[];
			var delay_pt=[];
			//rotation受渡変数配列
			var rotate_v=[];
			//動きの分類
			moveType="";

			//標準パターン番号削除未使用
			var patternflag=false;
			//パターン番号未使用
			var pattern_no=0;

			//多目的判定用
			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;
			//逆転フラグ
			var chg_v=Math.floor(Math.random()*2);
			if (chg_v < 1) {chg_v=-1;}

			//タイプ決定フラグ未使用
			var typeflag=0;

			//delay番号
			var delay_no=Math.floor(Math.random()*11);

			//delayed遅延させる/20%
			var delayed=Math.floor(Math.random()*5);
			//半径、幅の60%で外側配置
			var radius=Math.floor(box_W*0.6);


			//配置disposition位置番号/加算値
			var disposition_no=Math.floor(Math.random()*8);
			var disposition_X=0;
			var disposition_Y=0;

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

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

			//透明度
			var alpha_no=Math.floor(Math.random()*2);
			//速度補正係数
			var spd_v=1;

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

			//回転の場合の食み出し防止、長いので見える、透過させる
			if (split_h == 1 || split_v == 1) {
				if (rotate > 0) {alpha_no=0;}
			}

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

			//Bitmap配置、配置条件設定
			var vx=0,vy=0,angle_v=0;
			var shc=(split_h/2)-0.01;
			var svc=(split_v/2)-0.01;
			var diag_no=0;
			var v_x=0;
			var v_y=0;
			flag3=1;
			var k=0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

					//仮想ポイント/計算用の仮想位置
					virtual_X[k]=chip_pos_X[k]+chip_W[k]/2;
					virtual_Y[k]=chip_pos_Y[k]+chip_H[k]/2;

					//中子戻り位置
					set_pos_X[k]=0;
    					set_pos_Y[k]=0;

					//移動加算値等の計算
					switch(disposition_no){
						case 0://その場所で
							disposition_X=0;
							disposition_Y=0;
							spd_v=0.5;
						break;
						case 1://XY内部ランダム位置
							disposition_X=Math.floor(Math.random()*box_W)-virtual_X[k];
							disposition_Y=Math.floor(Math.random()*box_H)-virtual_Y[k];
							spd_v=1;
						break;
						case 2://中央OK
							disposition_X=box_W/2-virtual_X[k];
							disposition_Y=box_H/2-virtual_Y[k];
							spd_v=0.8;
						break;
						case 3://外側に、radius半径補正あり/仮想ポイントとの差を移動OK
							var angle=Math.random()*360;
							disposition_X=(Math.cos(angle)*radius+(box_W/2))-virtual_X[k];
							disposition_Y=(Math.sin(angle)*radius+(box_H/2))-virtual_Y[k];
							scale_no=0;//補正
							spd_v=1.5;
						break;
						default://その場
							disposition_X=set_pos_X[k];
							disposition_Y=set_pos_Y[k];
							spd_v=1;
					}

					//スケール方向決定
					switch(scale_no){
						case 0:
							scale_X=0;scale_Y=0;
						break;
						case 1:
							scale_X=1;scale_Y=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値の決定 90度x、逆転有り
					rotate_v[k]=rotate*90*chg_v;

					//回転の変化、回転0以外なら交互逆転する、確率33%
					if (chgflag == 1) {rotate_v[k] *= flag3;}

					//初期の移動
					//IN
					if (inType) {
    						//一括補正/細部補修の必要あり
						mov_pos_X[k]=disposition_X;
						mov_pos_Y[k]=disposition_Y;
						//CSS
						transboxs[k].css({translate:[mov_pos_X[k],mov_pos_Y[k]],rotate:rotate_v[k],scale:[scale_X,scale_Y],'opacity':alpha_no});
					}

					//OUT
					if (!inType) {
						//一括補正/細部補修の必要あり
						mov_pos_X[k]=disposition_X;
						mov_pos_Y[k]=disposition_Y;
						//XY位置はそのままで良い
						transboxs[k].css({translate:[0,0],rotate:0,scale:[1,1],'opacity':1});
					}

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

			//delay_no10 ランダムを減らす30%
			if (delay_no == 10 && chgflag) {delay_no=0;}

			//delayの計算/通常より増やした
			var sh=split_h-1;
			var sv=split_v-1;
			var flag3=1;
			var kk=0;//方向違いカウント
			var kkk=0;//半分でカウントダウン
			var k3=0;//逆斜め
			var k=0;
			for (var i=0; i < split_h; i++) {
				for (var j=0; j < split_v; j++) {

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

					if (delay_no < 2) {delay_st[k]=(i+j)*delay_speed;}//斜め
					if (delay_no > 1 && delay_no < 4) {delay_st[k]=k3*delay_speed;}//左右逆斜め
					if (delay_no == 4) {delay_st[k]=(i+j+k/split_total/4)*delay_speed;}//滑らか

					if (delay_no == 5) {delay_st[k]=(1+kkk*0.05)*delay_speed;}//ほぼ同時
					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()*split_total)/2*delay_speed;}//適当なランダム

					if (delay_no > 10 ) {delay_st[k]=k*2*delay_speed;}

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

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

					k++;
					flag3 *=-1;

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

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

			}

			//移動、z-index変更はで狂うので先に実行
			topbox.css({'left':0});

			//配列
			var number=[];
			for (var i=0; i < split_total; i++) {
				number[i]={'id':i,'delay':Math.floor(delay_st[i])};
			}
			//配列をソート/delayの昇順にsort
			number.sort(function(a,b) {
				var x=a.delay;
				var y=b.delay;
				if(inType){return x > y ? 1 : -1;}//IN昇順
				if(!inType){return x < y ? 1 : -1;}//OUT降順
			});

			for (var i=0; i < split_total; i++) {
				var dno=number[i].id;
				//ラップ無し
				transboxs[dno].css({'z-index':i});
			}

			//text_set("inType/ "+inType+" / disposition_no "+disposition_no+" / delay_no "+delay_no);

			//並び替えに時間がかかるので調整
			setTimeout(function() {

				//移動ここではまずい
				//topbox.css({'left':0});

				//アニメの実行
				var k=0;
				var params={};
				for (var i=0; i < split_h; i++) {
					for (var j=0; j < split_v; j++) {

						if (inType) {
							transboxs[k].delay(delay_st[k]).transition({translate:[0,0],rotate:0,scale:[1,1],'opacity':1},speed,"ease",function(){
								sliceflag ++;
								//終了
								if (sliceflag == split_total) {finshAll();}
							});

						}
						if (!inType) {
							transboxs[k].delay(delay_st[k]).transition({translate:[mov_pos_X[k],mov_pos_Y[k]],rotate:rotate_v[k],scale:[scale_X,scale_Y],'opacity':alpha_no},speed,"ease",function(){
								sliceflag ++;
								//終了
								if (sliceflag == split_total) {finshAll();}
							});
						}

						k++;

					}
				}

			},800);//500-1000
		}

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

			//全てが完了してから下画像表示
			if (inType) {
				imagebox.children("img").attr({'src':assets[image_no]}).css({'display':'block'});
			}

			topbox.empty();
			topbox.css({'left':imageW});

			//クリア
			globalflag=true;
			keep_url=assets[image_no];

			//遅延
			setTimeout(function() {

				text_set("AUTO");
				//タイマー次ぎ開く
				if (timer_use == 'use') {
					set_timer();
				}

			},500);

		}

		//スライス要素の位置大きさ決定、保存
		function slice_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++) {
					//大きさ保存
					chip_W[k]=slice_W;
					if (i == slh-1) {chip_W[k]=slice_Wb;}
					chip_H[k]=slice_H;
					if (j == slv-1) {chip_H[k]=slice_Hb;}
					//位置保存中央補正前
					chip_pos_X[k]=(slice_W*i);
					chip_pos_Y[k]=(slice_H*j);
					k ++;
				}
			}
		}

		//image-load、1画像ロード
		function imageload() {
			//
		}

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

			text_set("Loading Now!");
			//Loading
			loading.css({'display':'block'});

			//画像マルチローダーに進む
			imageload_count=0;
			multiLoader();

		}

		//画像複数ローダー1
		function multiLoader() {

			//画像Load終了判定
			if(imageload_count < loadImage_len) {
				//読み込み
				getLoadImage();
			} else {
				//終了
				multicomplete();
			}
		}

		//new Image()の実行
		function getLoadImage() {

			//new Loader
			var image_loader=new Image();
			image_loader.onload=function() {

				//サムネールURL保存
				assets.push(imagelist[imageload_count]);
				//次画像のロード
				imageload_count ++;
				multiLoader();
			}
			image_loader.onerror=function() {

				//カウントアップのみ
				imageload_count ++;
				multiLoader();
			}
			//URL
			image_loader.src=imagelist[imageload_count];
		}

		//全ての画像読み込み完了
		function multicomplete() {

			//画像数確認、再計算
			image_max=assets.length;
			//簡易TEXT
			text_set("Loading End!");
			//Loading
			loading.css({'display':'none'});
			//時間調整
			setTimeout(function() {
				//分割描画
				imagedraw();
			},1000);

		}

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

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

		}
		//タイマー
		function set_timer() {

			//タイマー再セット
			if (timer_use == 'use') {

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

		}

		//TEXT表示
		function text_set (t) {
			if (text_use) {
				textview.text(t);
			}
		}

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

	});

})(jQuery);


CSS

注意、各々の構成要素には適当なz-indexが必要です。

slice-transition-st.css


/* slice-transition-st.css 日本語 */
/* image-box-base */
#image-box-base {
position:relative;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
background:url("/main/images/welcome_back4.jpg") no-repeat center center;
background-color:#000000;
overflow:hidden;
z-index:1;
}

/* image-box */
#image-box {
position:absolute;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
z-index:2;
}
#image-box img {
padding:0;
margin:0;
}

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

#top-box .slice_bk {
position:absolute;
background-position: 0 0;
top:0;left: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;
z-index:4;
}
#text-view{
position:absolute;
top:0;left:0;
display:block;
width:630px;
height:16px;
padding:2px 5px;
font-size:12px;
color:#FF0000;
z-index:5;
}


その他

Loading画像



Loading画像なら何でも良い、また必要があればspin.jsを使用するまたはSVG画像でもよろしいと思います。
回転しないならばtransit.jsで回転させることは可能です。

 

参考、参照

CreateJSによるCanvas処理ですが、作り方はほぼ同じです。参考になるかはわかりませんが...

【参考】当方の記事: CreateJS 画像分割とテキストアニメーションの組み合わせ(最新)

サンプルである簡略したJSを、ボタン、サムネールボタン形式に改造しました。

【参照】当方の記事: jQuery CSS3 transit.js使用のボタン式画像分割アニメーション


画像

サンプル画像 / 原則 使用者が用途に応じてご用意ください。デモページより取得できます。

 

暑中お見舞い申しあげます。以上です。

 


[ この記事のURL ]


タグ:slice , css3 , Transition , jquery

 

ブログ記事一覧

年別アーカイブ一覧



[1]