POPSブログ

jQuery CSS3 3D回転Carouselをtransit.jsで処理する

369

  Category:  jquery2015/10/07 pops 

CSS3 で作ったCarouselをjquery.transit.jsのtransitionアニメーションで回転させます。無理矢理応用していますが簡単に出来て便利です。当然少しクセが有ります。

 

jQuery CSS3 3D回転Carousel、テスト


ご注意、Chrome.Firefox.Opera.等、transform-style:preserve-3d対応のモダンブラウザでご覧ください(Chrome推奨)。IE系ブラウザではご覧になれません。但し、Safari、Android系の動作は不明です。


zu

 

CSS3でCarouselを作りtransit.jsでアニメーション

CSS3でCarousel等の構造を作り、transit.jsでアニメーションする試みです。
但し、transform-style:preserve-3dを使用しますので、まだ未対応のブラウザもありますし、且つtransit.jsがZ軸に対応していませんので、完全に機能しない場合も有ります。
それでも、そこそこ動きますので多少は重宝するかも知れません。考えてみれば大変無謀なことです。

 

1. 3Dに未対応のブラウザが多い。(Chrome推奨)
2. transit.jsがZ軸に対応していませんので設定しても機能しないものもある。
(無理やり動かしています、試してみて機能するものだけ利用します、問題があれば当然ゴマカシます)
3. 構造とCSS3設定で大きく違いがあるので試行錯誤が必要です。
(前ページのCubeと構造が違うので注意ください)
4. 現在、transit.js対応はAndroid系が含まれていませんので動作は不明です。
5. この記事は2015/10/時点のテスト結果です。(transit.js V0.9.12)


● jquery.transit.jsの改造は[ こちら ]です。(秘密の袋とじ特集)

 

DEMO jQuery CSS3 3D回転Carousel(Y軸回転)

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


Chromeでの閲覧推奨、デモのHTML JS CSSは各デモページに有ります。

1 ノーマルCarousel、jquery.transit.jsは現在Z軸に対応していません。2015/10

DEMO-029


2 画像表示Carousel、上記デモに画像を挿入。

DEMO-029b


3 Z軸対応に改造Carousel、こちらはjquery.transit.jsを改造したもので特殊です。

DEMO-029c



 

簡単な説明


CSS3 transition Carousel等の構造を作り回転させるの説明


Y軸方向に回転し対応するパネルが最前面に来ます。
一旦、縮小して回転、その後所定の大きさに戻します。 transit.jsを利用しますので複数のtransition()を連続して実行出来ます。(現在、Z軸未対応3Dのため必ず思うようにはならない場合あり)

 

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

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

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

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

 

デモのHTML JS CSSについて

デモページに記載しています。


HTMLの構造について

他の場合と違い、角丸陰影をつけていますので、1構造多くなっています。(#carousel-3d-baseで角丸陰影をつけるとずれる)

私の習性として「角丸陰影」は絶対条件なのです。


<div id="carousel-base-wrap">
	<div id="carousel-3d-base">
		<div id="carousel-3d">
			<div id="photo-elem0" class="elem-3d">1</div>
			<div id="photo-elem1" class="elem-3d">2</div>
			<div id="photo-elem2" class="elem-3d">3</div>
			<div id="photo-elem3" class="elem-3d">4</div>
			<div id="photo-elem4" class="elem-3d">5</div>
			<div id="photo-elem5" class="elem-3d">6</div>
			<div id="photo-elem6" class="elem-3d">7</div>
			<div id="photo-elem7" class="elem-3d">8</div>
			<div id="photo-elem8" class="elem-3d">9</div>
		</div>
	</div>
</div>

当然、JS側で生成することも可能です。


JSについて

説明用に下記で「デモ」のJSを表示します。ノーマルCarousel、transition-carousel.jsの例

DEMOのJS


//transition-carousel.js
//Y軸3D回転Carousel

//Carousel-H
(function($){

	$(function () {

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

		var transit_speed=1000;//3D回転速度
		var scale_speed=600;//縮小拡大速度
		var scale_v=0.65;//縮小値 0.5-0.8

		//ベースの大きさ
		var bace_W=640;
		var bace_H=300;
		//エレメントの数
		var carousel_len=9;
		//エレメントの大きさ
		var elem_W=120;
		var elem_H=100;

		//半径
		var radius=200;

		//接する半径計算
		//radius=Math.round(elem_W/2/Math.tan(deg2rad(40/2)));
		//radius=Math.round((elem_W/2)/Math.tan(Math.PI/carousel_len));

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

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

		var moveflag=false;//アニメ中判定
		var elem=[];//エレメント保存用

		//オブジェクト保存
		var carousel_3d_base=$('#carousel-3d-base');
		var carousel_3d=$('#carousel-3d');

		//エレメント配置角度の計算
		var eleme_angle=360/carousel_len;

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

			var deg_v=i*eleme_angle + "deg";
			elem[i]=$("#photo-elem" + i);

			//CSS3設定、rotateYを先に
			elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(0) translateZ(' + radius +'px' + ')'});

			//エレメントを虹色に染める
			var angle_c=i/carousel_len;//0-1
			var rgb=hslToRgb(angle_c,1,0.5);//RGB
			var color=getHexString(rgb[0],rgb[1],rgb[2])//#FFFFFF形式
			elem[i].css({'backgroundColor':color});

		}

		//移動と回転
		carousel_3d.css({transform:'translateZ(-200px) rotateZ(-15deg)'});

		//alert(carousel_3d.css('transform'));

		//重要、初期のCSS設定/どんな場合も必要です/どんな場合も必要です/カスタム
		carousel_3d.css({scale:[1,1],scaleZ:1,rotateX:-10,rotateY:0});//使用するもの

		//3D回転/delayはdelay()でするFirefox180度対策
		function rotate3d_box(angle){

			moveflag=true;//回転中判定

			//縮小
			carousel_3d.transition({scale:[scale_v,scale_v]},scale_speed,function(){

				//3D回転
				$(this).delay(250).transition({rotateY:angle},transit_speed,"linear",function(){

					//縮小を戻す
					$(this).delay(250).transition({scale:[1,1]},scale_speed,function(){
						//完了
						moveflag=false;

					});

				});

			});

		}

		//クリックアクション/回転はマイナス設定
		$("#rotateChg-box span").each(function(i){
			var hitno=i;
			var angle=0;
			var angle_v=360/carousel_len;//角度

			$(this).click(function(e) {

				if(moveflag){return false;}

				$(this).addClass("setcolored");
				$(this).siblings("span").removeClass("setcolored");
				//マイナス値
				angle=angle_v*i*-1;rotate3d_box(angle);

				return false;
			});
		});

		//------------------------------------------------
		//degをradに変換
		function deg2rad(deg){
    			var rad=deg*Math.PI/180;
    			return rad;
		}

		//------------------------------------------------
		//HSL変換
		function hslToRgb(h,s,l){

			var r,g,b;
			if(s == 0){
				r=g=b=l;//achromatic
			}else{

				function hue2rgb(p, q, t){
					if(t<0) t +=1;
					if(t>1) t -=1;
					if(t<1/6) return p+(q-p)*6*t;
					if(t<1/2) return q;
					if(t<2/3) return p+(q-p)*(2/3-t)*6;
					return p;
				}

				var q=l < 0.5 ? l *(1+s):l+s-l*s;
				var p=2*l-q;
				r=hue2rgb(p,q,h+1/3);
				g=hue2rgb(p,q,h);
				b=hue2rgb(p,q,h-1/3);
			}

			return [Math.round(r*255),Math.round(g*255),Math.round(b*255)];
		}
		//------------------------------------------------
		//RGB数値を#000000形式に変換
		function getHexString(r,g,b) {
			var color="#"+("0"+parseInt(r).toString(16)).slice(-2)+("0"+parseInt(g).toString(16)).slice(-2)+("0"+parseInt(b).toString(16)).slice(-2);
			return color;
		}
		//------------------------------------------------

	});

})(jQuery);



CSS3について

順序が異なりますが、CSS3設定でCarouselを作る時にrotateX translateZの設定順序が重要です。

z-indexの位置に注意ください。設定がちがうと、3Dが消えたり角丸に成らなかったりします。
この構造での、CSS3設定で大事なことは、rotateX translateZ の設定順序を次の様にして下さい。
順序が違うと構造が出来ません。(前ページの構造ではこの反対でした...)
(理由はわかりません、フシギちゃんです、基準としてその様に成る様できていて、おそらくこちらが正式と思います)


hen

 

最重要。この構造では全ての部材のtransform設定は、rotateYを最初に書くこと。
下記は、CSSで書いた場合です。


rotateYを最初に書く

#photo-elem0{
transform:rotateY(0deg) translateZ(200px);
}
#photo-elem1{
transform:rotateY(40deg) translateZ(200px);
}

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

これはダメです、収束して外周に配置なりません

#photo-elem1{
transform:translateZ(200px) rotateY(40deg);
}

transformのCSS設定は後で変更が難しい。新たなプロパティを追加すると破壊する場合がある。


直接CSSを設定する例

CSSで設定の場合の例、必ずrotateYを先に記載してから、rotateXを設定。rotateXを設定しない場合は (0deg、または記載しない) にすれば良い。

rotateXは上下にズレマスので、入れ子を作り、そちらに設定した方がベターです。
数が多いと面倒だ。書く前からイヤになる。



#photo-elem0{
transform:rotateY(0deg) translateZ(200px) rotateX(10deg);
}
#photo-elem1{
transform:rotateY(40deg) translateZ(200px) rotateX(10deg);
}
#photo-elem2{
transform:rotateY(80deg) translateZ(200px) rotateX(10deg);
}
#photo-elem3{
transform:rotateY(120deg) translateZ(200px) rotateX(10deg);
}
#photo-elem4{
transform:rotateY(160deg) translateZ(200px) rotateX(10deg);
}
#photo-elem5{
transform:rotateY(200deg) translateZ(200px) rotateX(10deg);
}
#photo-elem6{
transform:rotateY(240deg) translateZ(200px) rotateX(10deg);
}
#photo-elem7{
transform:rotateY(280deg) translateZ(200px) rotateX(10deg);
}
#photo-elem8{
transform:rotateY(320deg) translateZ(200px) rotateX(10deg);
}

● エレメントのオブジェクト保存

仮にJS側でCSS設定などシナクトモ、パネルのオブジェクトだけは保存した方が便利です。
IDで保存した方が動作は速くなります。



//エレメントのオブジェクト保存
$("#carousel-3d .elem-3d").each(function(i){

	//elem[i]=$(this);
	elem[i]=$("#photo-elem" + i);//同じ

	//エレメントを虹色に染める
	var angle_c=i/carousel_len;//0-1
	var rgb=hslToRgb(angle_c,1,0.5);//RGB
	var color=getHexString(rgb[0],rgb[1],rgb[2])//#FFFFFF形式
	elem[i].css({'backgroundColor':color});

});

全てJS側で、CSSなどの設定を行った方が有利であるともい言える。


JSでCSSを設定する例

このデモのJSではJS側でCSS設定していますので次の様にしています。

よって、Cubeの面のCSSも次の様にJS側で設定可能です。(動的にも生成可能になります)
パネル個別に制御したい目的もあり、JSで操作しています。

rotateXはここで設定しないほうが良い。出来れば入れ子にして中の要素を傾ける。



var elem=[];//エレメント保存用

//オブジェクト保存
var carousel_3d_base=$('#carousel-3d-base');
var carousel_3d=$('#carousel-3d');

//エレメント配置角度の計算
var eleme_angle=360/carousel_len;

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

	var deg_v=i*eleme_angle + "deg";
	elem[i]=$("#photo-elem" + i);

	//CSS3設定、rotateYを先に
	elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(0) translateZ(' + radius +'px' + ')'});

	//エレメントを虹色に染める
	var angle_c=i/carousel_len;//0-1
	var rgb=hslToRgb(angle_c,1,0.5);//RGB
	var color=getHexString(rgb[0],rgb[1],rgb[2])//#FFFFFF形式
	elem[i].css({'backgroundColor':color});

}


//CSS3設定、rotateYを先に
elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(0deg) translateZ(' + radius +'px' + ')'});

直接CSSで設定していて、後でパネルのX軸のみ変えてみようとすると、「完全破壊」するから困ります。
X軸の設定は傾きますから、バーチカルタイプ、もしくは球形などを作るた為のようです。


#photo-elem1{
transform:translateZ(200px) rotateY(40deg);
}

elem[i].css({transform:'rotateX(-30deg)'});

その他の rotateY translateZ 設定をも合わせて再設定すれば、後でrotateXを修正できる。


for (var i=0; i < carousel_len; i++) {
	var deg_v=i*eleme_angle + "deg";
	//CSS3設定、rotateYを先に
	elem[i].css({transform:'rotateY(' + deg_v + ')' + 'translateZ(' + radius +'px)' + 'rotateX(-15deg)'});
	//または
	//elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(-15deg) translateZ(' + radius +'px' + ')'});
}


HTMLの構造とCarousel構成

このデモでのCSS3の処理は下図の様になります。パネルの面をrotateY回転、それぞれを半径分translateZ移動させています。(translateZは半径であり全て同じ値です)
rotateXは回転させていませんので傾けることは可能です。ステージに対してパネル(またはパネルラップ)は小さいため中央に top left で移動して表示しています。
円形に配置するには便利で簡単に変化させる事が出来ます。


zuzu

 


<div id="carousel-base-wrap"> 角丸陰影処理用
	<div id="carousel-3d-base"> Carouselの親(ステージ)
		<div id="carousel-3d"> パネルのラップ(Carousel本体)
			<div id="photo-elem0" class="elem-3d">1</div> パネル要素
			<div id="photo-elem1" class="elem-3d">2</div> パネル要素
			<div id="photo-elem2" class="elem-3d"><img /></div> 画像挿入パネル要素
			.
		</div>
	</div>
</div>

1. .elem-3dクラス、パネル部分がCarouselの回転する各要素になります。
(rotateY回転して、半径分translateZで移動して作る)
2. #carousel-3d、パネルのラップが各要素を纏めたCarousel本体になります。中央に top left で移動して表示。
(パネルのラップを移動させる場合はパネルと同じ大きさにして下さい)
3. #carousel-3d-baseCarouselの遠近感を付けるにはCarouselの親(ステージとでも呼んでおきます)が必要になります。perspectiveを設定するDIVです。
4. #carousel-base-wrap、一番外側のDIVは角丸陰影処理のための階層です。ステージに処理するとずれるので増やしています。
6. CSS3では回転などを設定すると、初期CSSの大きさの中央が回転の中心点になります。
7. 最初に作ったCarouselを後でJSで修正するのは非常に困難になります。場合により「完全破壊」します。


zuzu-no-zu

 

CSS3レーヤー上に描画されますが、パネルのラップの大きさはパネルの大きさにします。


● パネルのラップが「パネルと同じ大きさ」であれば中央に移動する計算が簡単になります。
left値は、(ステージ幅 - パネル幅)/2、top値は、(ステージ高さ - パネル高さ)/2、で計算できます。


● パネルのラップが「ステージと同じ大きさ」であれば、各「パネル」を中央に移動させます。
上記のほうが簡単と思います。

zuzu

パネルの大きさがマチマチの場合に有効かと思います。振る舞いは同じです。


● perspective設定値に応じて、最前面のパネルは拡大されます。パネルを「原寸」で表示したい場合は、パネルのラップのtranslateZ値を半径分マイナス移動させます。


carousel_3d.css({transform:'translateZ(値)'})利用の場合、(正式に対応してはいません)

パネルの親であるラップが position:relative の場合は、translateZ軸位置移動が可能のようです。
パネルの親であるラップが position:absolute の場合は、translateZ軸位置移動が出来ない様です。



#carousel-3d{
position:relative;
}

//translateZはZ軸位置移動
carousel_3d.css({transform:'translateZ(-200px)'});

本来は、position:absolute; と思います


#carousel-3d{
position:absolute;
}

translateZ軸位置移動出来ないので記載しても無効になる

translateZが機能する3D対応のJSなら、問題は出ない。(構造によっては何があるかわからない...)


Carousel回転のぶれゆがみなどがでる

現時点ではZ軸のアニメーションが出来ませんので、Z軸設定次第では意にソグワナイ動作になる場合があります。
rotateZをrotateに置き換えるなどの工夫をすれば多少防げるが、無理していますので不具合は当然です。


transform不具合の修正方法

.css({transform:'translateZ...'})等を再設定すると、全て壊れてしまいますので困ります。
色々な修正テストをしましたが、一部修正なっても、連続したjquery.transit.jsアニメーションには難しい。


1. 3D対応のJSを使ってtransform不具合が出ないようにする。
(jquery.transform.jsを使用すれば、CSS修正できますが.....余り意味無し)
2. jquery.transit.jsをZ軸の制御を出来る様に改造する。
(極近い将来にはバージョンUPで変わると予測していますが、IE系統が問題なのでしょう)
3. 簡単に改造できますので、次期バージョンが出るまで、改造のJSを利用することにしました。
(css({transform:'translateZ...'})の記述が、3Dの様式に変わりますので問題はでません)


// jquery.transit.jsの改造 //

切り取り線よりハサミで開封してお楽しみ下さい

[ヤバイ袋とじ記事] ----------------- 切り取り線 ---------------


translateZ、rotateZ、scaleZ、が機能するようにするだけです。
MINIタイプではない、githubにある、jquery.transit.jsを用意して、下記部分を加筆し保存(または上書き)します。
私の場合区別のためJS名を、jquery.transit.custom.js にしました。超簡単です。

● githubでのJSのダウンロード : jQuery Transit

改造、および使用は自己責任で行ってください。



hooksにそれぞれのregisterCssHook()を追加します

## Other CSS hooks
registerCssHook('scaleZ');
registerCssHook('translateZ');
registerCssHook('rotateZ');

setter、rotateの最後にrotateZ、translateZの処理を追加します

setter: {
// ### rotate

rotateZ: function(theta) {
 this.rotateZ = unit(theta, 'deg');
},

translateZ: function(theta) {
 this.translateZ = unit(theta, 'px');
},

以後、次のZ軸の記述が使えます。transition() css()も同様です。


対象オブジェクト.transition({translateZ:値}....)
対象オブジェクト.transition({scaleZ:値}....)
対象オブジェクト.transition({rotateZ:値}....)

但し、3つとも、下記のようには使用できません
{translate:[0,0,0]} //ダメ
{z:-200} //ダメ

Z軸の処理を分離して加筆します
対象オブジェクト.transition({translate:[0,0],translateZ:-200,...}....)

scaleZ、rotateZも同様です

アニメ中のズレゆがみなどの不具合も拡大縮小でZ軸を与えれば、ほとんど正常に変化するようです。


対象オブジェクト.transition({scale:[0.5,0.5],scaleZ:0.5,...}....)

kiken-ga-abunai笑っちゃうほど、超便利。問題は解決。



transitionアニメーション開始時の初期設定

css({transform:'rotateZ(値)'})、等とZ軸等を変更しても、transition.jsでは2D状態の時があります。
また必ずZ軸設定するとは限りません。
css({transform:'xxxxx'})等の設定は他に方法が無いため利用しているに過ぎない。
そのため、アニメーション開始前に必要なCSS初期設定をtransition.jsで行います。これで3D状態になります。
この処理をしないと、最初のアニメーションに違和感が出たり思い道理に動きません。
(2Dの状態からはアニメが始まると、perspectiveが効かず、途中でperspectiveが効いてくるので変になる)
carousel_3d.css('transform')で transform の状態を取得すると状況が判る。
下に例をあげます。


transformの状態を確認する。


alert(carousel_3d.css('transform'));

必要なものは複数個を一括設定する。
transformの状態が2Dの時がある。(Z軸設定0はmatrix()のまま)


//CSSで移動
carousel_3d.css({transform:'translateZ(-200px) rotateZ(-15deg)'});
//carousel_3d.css({transform:'translateZ(0px) rotateZ(0deg)'});

場合によってはmatrix()のまま
matrix(1, 0, 0, 1, 0, 0)

初期のCSS設定のtransformの状態


//重要、初期のCSS設定/どんな場合も必要です
carousel_3d.css({scale:[1,1],rotateX:-10,rotateY:0});//使用するもの

matrix3d()に成る
matrix3d(0.965926, .... 0, -200, 1)

transitionアニメーションは初期CSSの状態からの変化ですから、matrixには関係なく、初期CSS設定が重要です。


表示画像の大きさ調整

一般に手前のパネルは拡大されます。半径である、translateZ、および、perspective値によって大きさが違いますので。拡大縮小で原寸にするのが難しい。
パネルのラップ(Carousel本体)の translateZ を「半径分マイナス移動」させれば、原寸になります。


boke-ana

 

1. 目的により、移動して処理しなければならない場合がある。
2. translateZ を「半径分マイナス移動」させれば、perspective値に関係なく原寸になります。
3. perspective値が小さければ、遠近感は強調されます。
4. ベクター画像でない限り、通常の画像は拡大すればボケます。(jpg画像の品質がよければ2倍位までは以外と綺麗)


JSの中での .css() のtransform設定が可能です。但しCSSだけでtransitionアニメーションの中では使えません。
次の様な記述方法が可能です。(transit.jsは現在、Z軸に対応していないので仕方がない)

「複数同時の設定」は一括記載したほうが良い。


CSS設定はOK

オブジェクト.css({transform:'rotateZ(-15deg)'});

オブジェクト.css({transform:'rotateZ(-15deg) ..... '});

CSSの書式はアニメーションの書式と同じですから、アニメーションしますが、終了と共に乱れます。
matrix3dで内部処理がなされているのですが少し特殊なようです。(無理やり transition() ですから...)
つまり、現在、transit.jsのアニメーションでは使用出来ません。将来対応してくれるのか判りませんが...


アニメーションするが、そのあと乱れるので使えない

var carousel_3d=$('#carousel-3d');
//アニメーション
carousel_3d.transition({transform:'rotateZ(-15deg)'},速度,function(){

	終了と共に、ここで狂う、他にも影響があります

});
-----------------------------------------

CSSによって上書きされて全て狂ってしまうのが現状のようです

1つのオブジェクトに対して、1回限りなら使用できるが間違い易い。


他のJSでCSSのみ設定できないか

jquery.transform.jsでCSS設定だけに利用することも可能ですが、Carousel本体はZ軸に対応していないので変形する場合が多いので完全な問題解決とはならない。(動作のみ確認して即中止した)


//transform.js
carousel_3d.css("transform","translateZ(-200px) rotateZ(-15deg)");

perspectiveが設定時の画像縮尺について

前面に表示される画像は、perspectiveが設定されているため遠近感がでて、前面が拡大、後が縮小されますから、デモの様に画像の大きさとステージ(ベースのDIV)が同じ場合、画像の大きさを合わせることが困難です。
その様な場合に中心位置まで、translateZを後退させれば、最前面の縮尺は同じになります。


● 消失点とパネルラップのposition

パネルの親であるラップのtranslateZ軸位置移動をすれば表示の大きさが変えられます。
perspectiveの値によっても大きさが異なるため、translateZを半径分後退させるのは便利である。


パネルの親であるラップが position:relative の場合は、translateZ軸位置移動が可能のようです。
パネルの親であるラップが position:absolute の場合は、translateZ軸位置移動が出来ない様です。


● transit.jsは現在Z軸に未対応なので下記は「エラー」になる。


carousel_3d.css({z:'-200px'});

「パネルの親であるラップ」をパネルと同じ大きさにして「ラップ」を移動させても同じ結果です。


パネルの大きさ(パネルラップ)

● パネルの大きさは初期CSSが大事です。
パネルの中心点(回転中心)は初期CSSのパネルの大きさで決まります。
自動的に、パネルの中心が「回転中心」に成ります。中央に移動するにも大きさ設定が必要で、「回転中心」はパネル左上からの距離で固定されます。画像の大きさをJSで変更すると「回転中心」は固定されていますので結果的に「ズレテ」しまいます。


zuzu

 

重要、CSSの大きさと、JS初期設定の大きさと、必ず合わせてください。
合わないと、中心が狂い、回転時にブレテしまいます。


CSS

#carousel-3d .elem-3d{
display:block;
position:absolute;
top:0px;left:0px;
width:120px;
height:100px;
margin:0;
padding:0;
text-align:center;
font-size:50px;
font-weight:bold;
line-height:100px;
color:#EEEEEE;
border:#CCCCCC 1px solid;
opacity:1;
}

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

JS初期設定

//エレメントの大きさ
var elem_W=120;
var elem_H=100;

傾斜などの設定

「デモ」での構造とJSの場合です。またjquery.transit.jsのバージョンアップ等対応が変われば、変化があるかも知れません。(確実なことは言えません)

transformを個別に設定すると不具合がでるようですから「複数同時の設定」は一括記載したほうが良い。
jquery.transit.jsを改造した場合は、別の書式で個別に設定できます。


zuzuzu

 

● X軸で傾ける。
transform:'rotateX(角度)'で可能です。この場合「Z軸で傾ける」は機能しません。また少し変形するようです。
CSS設定はCarousel本体を縮小した場合Z軸の縮小が出来ないので少し揺らぐのが理由。

「複数同時の設定」は一括記載したほうが良い。


carousel_3d.css({transform:'rotateX(-10deg)'});
-------------------------------------------------------------
初期値だけで設定する場合、こちらが簡単です、揺らがない
carousel_3d.css({scale:[1,1],rotateX:-10,rotateY:0});

● Z軸で傾ける。(斜め)
transform:'rotateZ(角度)'で、Z軸で傾けるます。

「複数同時の設定」は一括記載したほうが良い。


//斜め
carousel_3d.css({transform:'rotateZ(-15deg)'});

● 複数同時の設定は一括記載したほうが良い。

複数の場合、下記の様に一括記載したほうが良いようです。順序によっても違いが出ますし、必ず機能するとは限らないようですから、色々とテストして決定します。(transformの実行に何らかのクセがあるのが原因のようですが...)


初期時、1回だけの設定になります。途中変更は壊れるので出来ません。(困るナ)


次の変化設定をを一括記載する1

移動、translateZ(-200px)
X軸で傾ける、rotateX(-10deg)
Z軸で傾ける、rotateZ(-15deg)
-------------------------------------------------------------
//OK
carousel_3d.css({transform:'translateZ(-200px) rotateZ(-15deg) rotateX(-10deg)'});
その場合、下の初期値は
carousel_3d.css({scale:[1,1],rotateY:0});

rotateXをtransit.jsの機能で操作する。


次の変化設定をを一括記載する2

移動、translateZ(-200px)
Z軸で傾ける、rotateZ(-15deg)
-------------------------------------------------------------
//OK
carousel_3d.css({transform:'translateZ(-200px) rotateZ(-15deg)'});
その場合、下の初期値は
carousel_3d.css({scale:[1,1],rotateX:-10,rotateY:0});

一括記載しないで個別に設定した場合、前の設定が無くなってしまいます。(上書きされて無くなる)


パネルのX軸を傾ける

中のパネルを傾けますので、パネル設定のループの中で設定します。(良い方法ではない)
または、CSSで直接設定します。

途中変更すると、Carouselが壊れます。
設定角度により上下にずれますので、「入れ子」を作りそれに設定した方が正確に成ります。(この下で説明)


最重要、基本的に「rotateYを先に設定」します。その後ほかのtransformを記載します。

「前ページ」の「Cubeを回転して画像...」では構造が違うために、最後に「rotateY」を設定しましたが「フシギ」な所です。


JSで設定する


//CSS3設定、rotateYを先に
elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(0deg) translateZ(' + radius +'px' + ')'});

パネルの傾斜は次の通りです。rotateで設定してもほぼ同じ結果です。


elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(-5deg) translateZ(' + radius +'px' + ')'});

elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotate(-5deg) translateZ(' + radius +'px' + ')'});

直接CSSで設定する
重要、rotateYを最初に書くこと。rotateXは最後でも機能します。


#photo-elem0{
transform:rotateY(0deg) rotateX(-10deg) translateZ(200px);
}
#photo-elem1{
transform:rotateY(40deg) rotateX(-10deg) translateZ(200px);
}
.
.

パネルに「入れ子」を作り傾ける

パネルに「入れ子」を作り、画像を表示した例ですが、色々と楽しめそうです。(寿司画像が最高おいしい)
(これが正式な方法と思います、下図では状態がわかる様に薄くパネルを表示しています)

gazoudaze

 

この際はパネル自体にrotateXを与えません。パネルに入れ子を作りその中に画像などを配置する場合に有効になります。

但し、backface-visibility:hiddenを与えた場合中の「画像はinline要素」になりますので、パネルは消えても画像は消えません。(便利な機能と思いや意外と使い難いです)
● 中の画像を回転するには、パネルにtransform-style:preserve-3d設定が必要です。(perspectiveはもとのままです)



<div id="photo-elem0" class="elem-3d"><img src="画像URL" /></div>

CSSは次の様になります。


#carousel-3d .elem-3d{
display:block;
position:absolute;
top:0px;left:0px;
width:100px;
height:100px;
margin:0;
padding:0;
border:#AAAAAA 1px solid;
transform-style:preserve-3d;
/*backface-visibility:hidden;*/
}
#carousel-3d .elem-3d img{
display:block;
position:relative;
top:0px;left:0px;
width:auto;
height:100%;
margin:0;
padding:0;
transform:rotateX(-30deg);
}

勿論、JS側から制御も可能になります。
通常のtransit.jsのCSS形式で設定、transition()での設定とtransformを利用した設定では振る舞いが違いますので注意ください。transition()での設定は動きます。
複数個有りますのでループで設定します。ループの形式は自由です。

パネルの中の画像の指定はjqueryの形式に従います。


● 通常のtransit.jsのCSS形式で設定、transition()での設定は箇条書きに並べることが可能です。


//エレメントのオブジェクト保存
for (var i=0; i < carousel_len; i++) {

	elem[i]=$("#photo-elem" + i);

	//例
	elem[i].css({borderRadius:'10px',boxShadow:'0 0 10px #000'});
	elem[i].children('img').css({rotateX:30});
	elem[i].children('img').transition({rotateX:30});

}

● transformの場合は1回限りで、複数一括設定ですから、なるべく利用しないほうが良い。


elem[i].children('img').css({transform:'rotateX(-30deg)'});

● each()、$(this)、でも設定できますが、elem[i]の方がID指定だから反応が早い。


//エレメントのオブジェクト保存
$("#carousel-3d .elem-3d").each(function(i){

	elem[i]=$("#photo-elem" + i);

	//例
	$(this).css({borderRadius:'10px',boxShadow:'0 0 10px #000'});
	$(this).children('img').css({borderRadius:'10px',boxShadow:'0 0 10px #000'});
	$(this).children('img').css({borderRadius:'8px'});

	$(this).children('img').css({rotateY:-75,rotateX:30});

});

半径の設定

半径は translateZ値 ですので、円周配置ですから全て同じ値です。


zuzuzunozu

 

● パネルの幅を考慮して、適当な半径にします。



//半径
var radius=200;

実行
elem[i].css({transform:'rotateY(' + deg_v + ')' + 'rotateX(0deg) translateZ(' + radius +'px' + ')'});

● パネルを合わせる(接する)場合は次の様にしますと接します。
パネル幅と角度の関係より計算します。但し前面は「拡大」しますので、若干隙が出ることがあります。
(問題があれば微調整ください、Math.floorよりMath.roundのほうが良い見たいです)


パネル幅 elem_W、角度 40度、分割数 carousel_len の場合の例です。


//半径
var radius=200;

//接する半径計算
radius=Math.round(elem_W/2/Math.tan(deg2rad(40/2)));

//degをradに変換
function deg2rad(deg){
    	var rad=deg*Math.PI/180;
    	return rad;
}

下記、簡易計算でも同じです。(こちらが簡単)


radius=Math.round((elem_W/2)/Math.tan(Math.PI/carousel_len));

CSS直接記載の場合は「原始暗算機」を利用ください。


画像の表示

● 背景画像の表示。
「デモ」ではパネル(div)を表示しています。例ではバック背景に画像を挿入しています。
直接、<img /> 形式でも <div><img /></div> 形式でも構いません。自由です。



#photo-elem0{
background:url("/main/images/testImage101.jpg") no-repeat center center;
}
#photo-elem1{
background:url("/main/images/testImage102.jpg") no-repeat center center;
}
#photo-elem2{
background:url("/main/images/testImage103.jpg") no-repeat center center;
}
#photo-elem3{
background:url("/main/images/testImage104.jpg") no-repeat center center;
}
#photo-elem4{
background:url("/main/images/testImage105.jpg") no-repeat center center;
}
#photo-elem5{
background:url("/main/images/testImage106.jpg") no-repeat center center;
}
#photo-elem6{
background:url("/main/images/testImage107.jpg") no-repeat center center;
}
#photo-elem7{
background:url("/main/images/testImage108.jpg") no-repeat center center;
}
#photo-elem8{
background:url("/main/images/testImage109.jpg") no-repeat center center;

● IMG構造で記述する。
デモではDIV構造ですが、IMG構造で記述することも出来ます。



<div id="carousel-base-wrap">
	<div id="carousel-3d-base">
		<div id="carousel-3d">
			<img id="photo-elem0" class="elem-3d" src="画像URL" />
			<img id="photo-elem0" class="elem-3d" src="画像URL" />
			<img id="photo-elem0" class="elem-3d" src="画像URL" />
			.
			.
		</div>
	</div>
</div>

transition()アニメーションについて

transit.jsではIE系がまだ機能しませんので、transform-style:preserve-3d に未対応です。
transform-style:preserve-3d 設定のオブジェクトをtransition()アニメーションするのですから、正常に機能しないのは当然です。(transit.jsがZ軸に対応すれば多少違ってくるかも知れない...)


重要、transit.jsで動かす故、transition()アニメーション前に「transit.jsの書式でCSSを初期化」します。
先に処理しないと、最初 perspective が狂います。その他も影響があるかも....


「Carousel本体」である「carousel_3dオブジェクト」は3Dになっていますが、通常、transit.jsで動かす場合は matrix() に変換されて動いているようです。
実際には、matrix3d()で動かしますので、下記の様にtransit.jsの「初期のCSS設定」をしますと matrix3d() に変換されます。

下記、transit.jsの「初期のCSS設定」をしないと、matrix()で始まり、matrix3d()に移行します。



//3dの設定
carousel_3d.css({transform:'translateZ(-200px) rotateZ(-15deg)'});

//重要、初期のCSS設定
carousel_3d.css({scale:[1,1],rotateX:-10,rotateY:0});

carousel_3d.transition({処理の書式},速度,function(){

	//3D回転
	$(this).delay(250).transition({rotateX:角度の値},速度,"linear",function(){

		$(this).delay(250).transition({処理の書式},速度,function(){

			//
		});

	});
});

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

次の様にするとmatrix3d()の値が取得できますので確認できます
var matrix=carousel_3d.css('transform');
alert(matrix);

matrix3dの中の値例
matrix3d(0.965926, -0.258819, 0, 0, 0.254887, 0.951251, -0.173648, 0, 0.0449435, 0.167731, 0.984808, 0, 0, 0, -200, 1)

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

3D設定が無く、matrix3d()の値を取得したい場合
変化のほとんどない値を設定する
carousel_3d.css({transform:'translateZ(-0.0001px)'});

matrix3dの中の値例
matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -0.0001, 1)

● delayによる遅延について。

通常、transit.jsでは transition() の中でdelayを利用できる仕様なのですが、処理内容によっては、Firefoxでうまく動作しないために、jQueryのdelay()を使用しました。



delayが機能しない場合があったり、乱れる

carousel_3d.transition({delay:600,処理の書式},速度,function(){
	//
});

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

こちらはOKです

carousel_3d.delay(600).transition({処理の書式},速度,function(){
	//
});

transform:matrix3dアニメーションについて

直接matrix3d()でアニメーションさせることも可能ですが、CSSを上書きするので連続させるのが困難です。
transit.jsが、Z軸に対応するまで待った方が無難と思います。(改造は可能のようだが使用しないので止めた)

matrix3d()はその都度値をつくるのが大変ですし、matrixは通常のアニメーションで利用するものではないので止めたほうが良い。



transform:'matrix3d()'
オブジェクト.transition({transform:'matrix3d(値)'},速度,function(){

	//一応動作するが、連続させるのが難しい

});

この辺の事情など、下記記事で解説されていますので参考ください。当方のテストでは連続のアニメにまでは至っていない。transit.jsとの連携なので少々時間がかかりそうだ。

【参考】qiita.comの記事: JavaScriptからCSSのtransform:matrix3dを扱う覚書


クリックアクション

● 「デモ」でのボタンの例です。
アニメーション中はボタンが機能しないようにしている。
別途ボタンなどを作る場合はそれに準じて作ります。

分割数の角度で回転配置していますので、マイナス値の角度を与えれば正面に来る理屈です。



//クリックアクション/回転はマイナス設定
$("#rotateChg-box span").each(function(i){
	var hitno=i;
	var angle=0;
	var angle_v=360/carousel_len;//角度

	$(this).click(function(e) {

		if(moveflag){return false;}

		$(this).addClass("setcolored");
		$(this).siblings("span").removeClass("setcolored");
		//マイナス値
		angle=angle_v*i*-1;rotate3d_box(angle);

		return false
	});
});

● パネルにクリックアクションを設定する場合

パネルの枚数と角度によっては見えなくなるものもあります。それでも線の描画が若干残ります。
見えない角度のパネルはクリックしても当然反応はしません。



//パネルにクリックアクション/回転はマイナス設定
$('.elem-3d').each(function(i){
	var hitno=i;
	var angle=0;
	var angle_v=360/carousel_len;//角度

	$(this).click(function(e) {

		if(moveflag){return false;}

		//マイナス値
		angle=angle_v*i*-1;rotate3d_box(angle);

		return false
	});
});

画像

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

 

最後に

ちょっとしたCSS設定の違いで構造が出来なくなったりしますので、判り難いと思いますが、詳細に記述しました。
transit.jsのバージョンアップなどの事由、または、transform-style:preserve-3d 対応に変わったりした時は書き換える可能性があります。
JSの変更などは自由ですが、問題がでましたら自己解決ください。


構造のCSSおよび、Transformsについては次のサイトが参考になります。

【参考】unformedbuilding.comの記事: CSS Transforms についてのメモ

【参考】desandro.github.ioの記事: Intro to CSS 3D transforms


ほとんど理解不能な解説をお読み頂いて真にありがとうございます。所でCarouselは必要ですか、....、私は必要有りません。
以上です。

 


[ この記事のURL ]


タグ:jquery , Transition , css3

 

ブログ記事一覧



[1]