今回は、前回の「マウスオーバーで平面が回転する3Dアニメーション」の応用編、グリッドレイアウトで並べた画像コンテンツを、立方体に見立てたキューブとして回転して別の面が表示されるパターンのCSSのtransform
を利用した3Dアニメーションサンプルをご紹介。
前回のTipsは以下をご覧ください。
それでは、前回の平面パネルのコードを元にして、今回はキューブの回転アニメーションを実装していきます。
まずはデモをご覧ください!
See the Pen
3D Cube Rotate Motion on Mouse Over by digistate (@digistate)
on CodePen.
INDEX
HTMLの構造
HTMLは前回の平面パネルの回転サンプルの構造と同じです。
<article> <div class="item"> <!-- 正面ここから --> <div class="item-img" style="background-image:url(画像URL);"></div> <!-- 正面ここまで --> <!-- 上面ここから --> <div class="item-content" style="background-image:url(画像URL);"> <h1>このパネルのタイトル</h1> </div> <!-- 上面ここまで --> </div> </article>
立方体(キューブ)の構造
マウスオーバーで回転するキューブの初期状態の配置は後述するCSSによって以下のようになっています。
キューブのラッパー(.item
)の中に、正面のパネル(.item-img
)と、マウスオーバーしたときにキューブが回転して表示される上面のパネル(.item-content
)があります。
CSSについては後述しますが、要素を立方体にするため、まずラッパー(.item)自体をarticleの高さの半分だけ奥側(Z軸マイナス方向)に移動させます。
次に、ラッパー内にある正面パネルは、逆にラッパーを奥に移動した分だけ前面(Z軸プラス方向)に出します。
最後に、マウスオーバーしたときにキューブが回転して表示されるように、まずは上面用パネル要素を上方向(Y軸マイナス)にarticle
の高さの半分だけ移動し、さらに倒して寝かせます(X軸を基準として90度回転)。
そうすると、上図のように正面パネル(.item-img
)と上面(.item-content
)が正面パネルの上辺に90度の角度で隣接した立体の状態になります。
マウスオーバー動作の流れ
今回は立方体要素を回転させるため、以下のような理屈で動作させています。
article
をマウスオーバー.item
(キューブの中心面)が前面(X軸マイナス)方向に90度回転- 正面パネルの上辺に直角に隣接している上面パネルが(
.item-content
)が前面になる
CSSの構成
article
Masonryのグリッド単位となる articleは 前回の平面パネルの回転のときと同じです。
article { width: 192px; height: 192px; -webkit-perspective: 1600px; perspective: 1600px; }
キューブの軸面となるラッパー(.item)
正面と上面のパネルを持つラッパー要素(.item
)は、以下のCSSを適用しています。
.item{ /* 高さ = 100% */ height:100%; /* 子要素の3Dの位置関係を保持 */ transform-style:preserve-3d; /* アニメーションの時間 */ -webkit-transition-duration:.3s; transition-duration:.3s; /* articleの高さの1/2だけ奥側(Z軸方向マイナス)に移動 */ -webkit-transform:translateZ(-96px); transform: translateZ(-96px); }
平面パネルの回転のCSSに、transform で 奥(Z軸マイナス方向)にarticleの高さの1/2移動する定義(transform:;translateZ(-96px)
)が加わっています。
パネル要素(.item-img, .item-content)
正面パネル(.item-img
)と上面パネル(.item-content
)要素は、基本は前回の平面パネルの場合と同じです。
.item-img, .item-content { position: absolute; top: 0; left: 0; width: 100%; height: 100%; /* 背景画像用の設定 */ background-size: cover; background-position: 50%; /* transform と transition によるチラつき防止 */ -webkit-backface-visibility: hidden; backface-visibility: hidden; }
平面パネルのサンプルと同様、ギャラリー画像はCSSではなくパネル要素のインラインのスタイルとして個別にセットしています。
<!-- 前面パネル --> <div class="item-img" style="background-image:url(画像URL);"></div> <!-- 背面パネル --> <div class="item-content" style="background-image:url(画像URL);"> <h1>パネルタイトル</h1> </div>
正面パネル(.item-img)の移動
正面パネルは、さらに以下ようにラッパー(.item)が奥に移動した分を手間に移動するためのスタイリングをします。
.item-img{ -webkit-transform:translateZ(96px); transform:translateZ(96px); }
上面パネル(.item-content)の移動
上面パネルは、正面パネルの上辺と直角に隣接するように、まずはY軸マイナス方向へarticleの高さの半分(96ピクセル)を移動し、90度回転させます。
.item-img{ /* 上(Y軸マイナス)方向に移動し、90度回転 */ -webkit-transform: translateY(-96px) rotateX(90deg); transform: translateY(-96px) rotateX(90deg); }
サイズパターンに合わせて移動距離を調整
今回のサンプルでは、グリッドのサイズが基準となる 192 x 192ピクセルの正方形以外に 3パターン(.wide, .long, .big)あるので、それぞれのサイズに合った3D化のスタイリングを行っておきます。
2倍サイズパネル(.big)の移動距離調整
/* 正面パネル: Z軸マイナスへ 394/2 = 192px 移動 */ article.big .item-img { -webkit-transform: translateZ(192px); transform: translateZ(192px); } /* 上面パネル: Y軸マイナスへ 394/2 = 192px 移動 */ article.big .item-content { -webkit-transform: translateY(-192px) rotateX(90deg); transform: translateY(-192px) rotateX(90deg); }
縦2倍サイズパネル(.long)の移動距離調整
/* 上面パネル: Y軸マイナスへ 394/2 = 192px、Z軸マイナスへ 192/2 = 96px 移動 */ article.long .item-content { -webkit-transform: translateY(-192px) translateZ(-96px) rotateX(90deg); transform: translateY(-192px) translateZ(-96px) rotateX(90deg); }
横2倍サイズのパネル(.wide
)については、高さは基準サイズと同じなので調整は不要です。
マウスオーバー時の回転
既にギャラリーの各要素は立方体として3D化されているので、あとはマウスオーバー(:hover)時に上面パネルが前面にくるように回転させるだけです。
article:hover .item { -webkit-transform: rotateX(-90deg) translateY(96px); transform: rotateX(-90deg) translateY(96px); }
軸面となる .item
は立体化のために articleの高さの半分(96ピクセル)を奥に移動してあるので、回転(rotateX(-90deg))と同時に手前に表示されるよう、戻します(translateY(96x))。
さらに、2倍サイズの .big
と 縦2倍サイズの .long
にもそれぞれ必要な調整をします。
article:hover.big .item { -webkit-transform: rotateX(-90deg) translateY(192px); transform: rotateX(-90deg) translateY(192px); } article:hover.long .item { -webkit-transform: rotateX(-90deg) translateY(192px) translateZ(96px); transform: rotateX(-90deg) translateY(192px) translateZ(96px); }
というわけで、今後のリリース予定のDigiPressのテーマにはこのテクニックを使ったアーカイブページを持つテーマも開発してみようと思います。