HTML5 × CSS3 × jQueryを真面目に勉強 – #10 CSS3 Transforms(2D)【20日目】

2012.12.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

そんな訳で、CSS3トランスフォームについて学習した内容をまとめておくとします。

はじめに - CSS3のトランスフォーム(変形)機能について

これまでにもCSS3の機能としてTransitionsAnimationsについて紹介してきました。CSS3 Transformsは、文字通りWebページを変形させたり新たな次元を加える事が出来るモノです。変形と一口に言ってもトランスフォーム機能には2D3Dとがあり、これらを同じくCSS3の機能であるアニメーションと組み合わせる事で、驚きの効果をWebページにもたらす事が出来てしまいます。

要素に対してどのような変形をするかの指定は、Transformプロパティの値に予め用意されているtransform関数を指定する事で実現します。

Transform(2D)の関数一覧
translate(tx, ty) 要素の平行移動
scale(sx, sy) 要素の拡大と縮小
rotate(deg) 要素の回転
skew(sx, sy) 要素の傾斜
matrix(a, b, c, d, e, f) 行列指定による2D変形

今回はTransform2Dに的を絞ってサンプルコードを交えながら順に見てくとします。

matrixですが、やや複雑な理屈で取っ付きにくいうえに、rotateやskewで同等の表現がまかなえてしまうため、今回の記事では割愛させて頂きます。
m(_ _)m

translate(tx, ty) - 平行移動

第一引数はX方向への移動距離、第二引数はY方向への移動距離を指定します。

記述例 - translate

transform: translate(400px);      // 第一引数のみを指定
transform: translate(100px, 400px);   // 第一引数、第二引数を指定
transform: translate(-400px, -100px); // マイナス値を指定

第二引数を省略すると、0として処理されます。

当記事執筆時点(2012年12月)では、transformプロパティに対してベンダープレフィックスをつけて指定する必要があります。

以下にサンプルを用意しました。マウスオーバーすると各スプライトが指定された値でアニメーション移動します。

translate1.css ※ベンダープレフィックスは省略していますが、実際のコードでは必要となります。

li {
  border-radius: 50%;
  color: #fff;
  display: inline-block;
  height: 150px;
  line-height: 150px;
  margin: 30px;
  padding: 15px;
  text-align: center;
  width: 150px;
  transition: 1s;
}

.t1 {
  background: #01b0f0;
}
.t1:hover {
  transform: translate(400px, 1em);
}

.t2 {
  background: #ff3588;
}
.t2:hover {
  transform: translate(100px, 400px);
}

.t3 {
  background: #aeee00;
}
.t3:hover {
  transform: translate(-400px, -100px);
}

translate1.html

<ul>
  <li class="t1">(400px)</li>
  <li class="t2">(400px, 100px)</li>
  <li class="t3">(-400px, -100px)</li>
</ul>

サンプルでは三種類の変形を用意しました。それぞれマウスオーバーすると指定した値で平行移動という変形をします。ただ単純にtranslateを指定しただけでは、マウスオーバー時に瞬時に状態変化するだけで分かり難いので、11行目でアニメーションを指定しています。

translateX()とtranslateY()

translate()はX方向とY方向の移動距離値を一括指定しますが、translateX()はX方向、translateY()はY方向の移動距離をそれぞれ個別に指定する関数です。

scale(sx, sy) - 拡大縮小

第一引数はX方向への縮尺比率、第二引数はY方向への縮尺比率を指定します。例えば1と指定すると等倍(初期状態)となり、2と指定すると2倍に拡大されます。

記述例 - scale

transform: scale(10);   // 第一引数のみを指定
transform: scale(-10);    // 第一引数にマイナス値を指定
transform: scale(10, 0);  // 第一引数、第二引数を指定

第二引数を省略すると、第一引数と同じ値で処理されます。

上の記述例を元にサンプルを作成しました。マウスオーバーすると各スプライトが指定された値で拡大縮小変形します。

scale1.css

.s1 {
  background: #01b0f0;
}
.s1:hover {
  transform: scale(10);
}

.s2 {
  background: #ff3588;
}
.t2:hover {
  transform: scale(-10);
}

.s3 {
  background: #aeee00;
}
.s3:hover {
  transform: scale(10, 0);
}

サンプルにあるように、引数にマイナス値を指定すると、スプライトが上下左右それぞれ反転した状態で拡大されているのが分かります。マイナス値に拡大と言葉で表すとピンとこないかもしれませんが、実際に動いているモノを見た上で、「そういうのもあるのか!」といった程度に押さえておけば良いです。

scaleX()とscaleY()

scaleX()はX方向、scaleY()はY方向への縮尺率をそれぞれ個別に指定します。どちらか一方のみを指定した場合、指定されなかった方は初期値として1が指定された状態で変形します。

rotate(d) - 回転

その名の通り要素を回転させる事が出来ます。引数に指定した値分の角度で時計回りに回転します。引数にマイナス値を指定する事で反時計回りに回転させる事も出来ます。

記述例 - rotate

transform: rotate(0);      // 初期値。回転しない
transform: rotate(90deg);  // 時計回りに90°回転
transform: rotate(-45deg); // 反時計回りに45°回転

0以外の値を指定する場合は、deg(※度という意味)を単位として付けます。

以下、サンプルを作成しました。回転だけでは少し味気ないので、ここではscale()との合わせ技に挑戦してみるとします。

sampleimg_rotate1sampleimg_rotate2sampleimg_rotate3sampleimg_rotate4

rotate1.css

.wrapper {
  background: #eee;
  box-sizing: border-box;
  height: 100%;
  position: absolute;
  overflow: auto;
  padding: 8px 60px;
  width: 100%;
  transition: 1s;
  transform: scale(1) rotate(0);
}
  .wrapper.hiding {
    transform: scale(0) rotate(720deg);
  }

rotate1.html

<div id="page1" class="wrapper">
  <h1>Rotate #1 | CSS3 transform</h1>
  <h2 id="toc-page-1">Page: 1</h2>
  <p>Lorem ipsum dolor sit amet, ...</p>
  <p>Lorem ipsum dolor sit amet, ...</p>
  <p>
    <a href="#" id="btnGo" class="btn btn-large btn-green">GO!</a>
  </p>
</div>

<div id="page2" class="wrapper hiding">
  <h1>Rotate #1 | CSS3 transform</h1>
  <h2 id="toc-page-2">Page: 2</h2>
  <img id="wakamsha" class="thumb" src="img/myLogo.jpg" />
  <p>Lorem ipsum dolor sit amet, ...</p>
  <p>
    <a href="#" id="btnBack" class="btn btn-large btn-pink">back!</a>
  </p>
</div>

rotate1.js

$(function() {
  $('#btnGo').click(function(e) {
    e.preventDefault();
    pageTransition('#page1', '#page2');
  });
  $('#btnBack').click(function(e) {
    e.preventDefault();
    pageTransition('#page2', '#page1');
  });

  function pageTransition(from, to) {
    var dfd = $.Deferred();
    dfd.then(function() {
      $(from).addClass('hiding');
    }).then(function() {
      setTimeout(function() {
        $(to).removeClass('hiding');
      }, 1000);
    });
    dfd.resolve();
  }
});

上にあるようにtransformプロパティにはスペース区切りで複数の関数を同時に指定することが出来ます。ボタンをクリックするとそれぞれのページ要素をアニメーションで変形させながら切り替え表示させています。

ちなみに以下の例のようにそれぞれの関数を個別に設定してしまうと、scale()がrotate()で上書きされてしまい、期待通りに動作しなくなりますので注意が必要です。

// NGパターン
transform: scale(0);
transform: rotate(720deg);

skew(sx, sy) - 傾斜

長方形を平行四辺形にするような感じで要素を傾斜させることが出来ます。第一引数はX方向への傾斜角度、第二引数はY方向"への傾斜角度を指定します。

記述例 - skew

transform: skew(30deg);       // 第一引数のみ指定。X軸に沿って30度傾斜
transform: skew(10deg, 20deg);    // 第一引数、第二引数を指定
transform: skew(-10deg, -20deg);  // マイナス値を指定

第二引数を省略すると、0として処理されます。つまりY軸方向には傾斜しません。

以下にサンプルを用意しました。マウスオーバーすると各スプライトがブラインドのような形状に変形します。

sampleimg_skew1sampleimg_skew2

skew1.css

.cube-container {
  background: #d6d6d6;
  border-radius: .4em;
  margin: 60px 100px;
  padding: 10px;
}
  .cube-container:hover .panel {
    margin-bottom: -20px;
    transform: skew(40deg, 6deg);
  }

.panel {
  background: rgba(58, 58, 58, 0.6);
  border: 1px solid #888;
  font-size: 1.4em;
  margin: 0 0 10px;
  padding: 20px;
  position: relative;
  opacity: .8;
  text-align: center;
  transition: 1s;
}

.color1 { background-color: #ff531f; }
.color2 { background-color: #262626; }
.color3 { background-color: #30a8ff; }
.color4 { background-color: #ff3588; }
.color5 { background-color: #aeee00; }

skew1.html

<ul class="cube-container">
  <li class="panel color1"><span>WAKAMSHA1</span></li>
  <li class="panel color2"><span>WAKAMSHA2</span></li>
  <li class="panel color3"><span>WAKAMSHA3</span></li>
  <li class="panel color4"><span>WAKAMSHA4</span></li>
  <li class="panel color5"><span>WAKAMSHA5</span></li>
</ul>

3DっぽいCubeを作ってみる

Transform2Dのテクニックのみを使って立体的な感じのCubeを作ってみるとします。3D変形用の関数も用意されていますが、2D変形だけでも十分に実現可能だったりします。

完成予想イメージはこんな感じです。

sampleimg_cube1sampleimg_cube2

ではひとつずつ実装していきます。

1 | HTMLコードを作成

cube.html

<body>
  <h1>Cube | CSS3 transform</h1>
  <p class="center"><a href="#"  class="btn btn-green">Transform!</a></p>
  <hr />
  <ul class="cube">
    <li class="panel top">1</li>
    <li class="panel left1">2</li>
    <li class="panel right1">3</li>
    <li class="panel right2">4</li>
    <li class="panel left2">5</li>
    <li class="panel bottom">6</li>
  </ul>
</body>

HTMLには特別なことは一切書いていません。手始めにul要素にCubeオブジェクトの各パネルを定義します。また、平面状態とCube状態を切り替えるためのボタン要素を3行目に定義しました。

2 | 見栄えの実装 - 平面状態

続いてCSSです。まずはCubeになる前の平面状態のスタイルを組んでいきます。

.cube {
  left: 50%;
  margin-left: -100px;
  padding: 0;
  position: fixed;
  top: 150px;
}
.cube .panel {
  background: #888;
  border-radius: 30px;
  color: #fdfdfd;
  font-size: 300%;
  height: 90px;
  margin-bottom: 10px;
  padding: 10px;
  text-align: center;
  vertical-align: middle;
  width: 90px;
  transition: 1s;
}

Cubeがウィンドウの真ん中に表示されるようにpositionプロパティをfixedにします。また、平面からCubeに変形する様子が分かるようにtransitionプロパティを指定してアニメーションを定義しました。

3 | 見栄えの実装 - Cube状態1

cube要素にtransformedクラスが追加されたら、Cubeになるようにしていきます。

.cube.transformed .panel {
  height: 180px;
  font-size: 600%;
  position: absolute;
  width: 180px;
}

パネルに対しpositionプロパティをabsoluteにすることで、Cubeっぽく見えるよう絶対配置できるようにします。

.cube.transformed .panel.top,
.cube.transformed .panel.bottom {
  background: rgba(255, 83, 31, 0.41);
  z-index: 60;
  transform: rotate(60deg) skew(0deg, -30deg) scale(1, 1.16);
}
.cube.transformed .panel.bottom {
  background: rgba(38, 38, 38, 0.39);
  top: 200px;
  z-index: 10;
}
.cube.transformed .panel.left1,
.cube.transformed .panel.left2 {
  background: rgba(48, 168, 255, 0.39);
  z-index: 50;
  transform: skew(0, 30deg);
}
.cube.transformed .panel.left2 {
  background: rgba(255, 53, 136, 0.4);
  z-index: 20;
}
.cube.transformed .panel.right1,
.cube.transformed .panel.right2 {
  background: rgba(174, 238, 0, 0.4);
  z-index: 40;
  transform: skew(0, -30deg);
}
.cube.transformed .panel.right2 {
  z-index: 30;
}

各パネルに対し、rotate()、skew()、scale()を組み合わせて指定することで、それぞれがCubeの側面に見えるように変形させます。さらにz-indexプロパティをつかって重なり順序を調整します。

3 | 見栄えの実装 - Cube状態2

最後に各パネルの座標を調整してCube状に見えるようにしていきます。各要素に対し、以下のプロパティを追加します。

.cube.transformed .panel.bottom {
  top: 200px;
}
.cube.transformed .panel.left1,
.cube.transformed .panel.left2 {
  left: -101px;
  top: 158px;
}
.cube.transformed .panel.left2 {
  z-index: 20;
  left: 100px;
  top: 42px;
}
.cube.transformed .panel.right1, .cube.transformed .panel.right2 {
  left: 100px;
  top: 158px;
}
.cube.transformed .panel.right2 {
  left: -100px;
  top: 41px;
}

これでCSSの方は完成しました。最後にtransformedクラスを付け外しするためのJavaScriptを記述します。

$(function() {
  $('.btn').click(function(e) {
    e.preventDefault();
    $('.cube').toggleClass('transformed');
  });
});

ここまでCSS3 Transform 2D変形の基本について紹介しました。次回はTransform 3D変形について学んだことを綴っていきます。

参考サイト