CSSで本当にクリアできるルービックキューブを作ったので3Dについて色々解説してみる その2

カテゴリ:3D 2013年8月28日 19:04

前回はこれから解説していくルービックキューブの紹介と、3D関連の学習に利用した記事などの紹介をしました。
いよいよ実際にルービックキューブについて解説をしていきたいと思います。
まずは基本的なところから始めて行くので、人によっては今回の記事はほぼ知ってることだらけになるかもしれません。

要素の変形 - transformプロパティの基礎

上でも書いた通り、まずはtransformプロパティの基礎から解説していきます。
すでに使ったことがある人ならおなじみだと思いますが、transformプロパティ(WebKit/Blink系はまだ-webkit-のプレフィクスが必要です)にはいくつかの値が指定できます。

実際にtransformプロパティに指定できる関数をいくつか適用したサンプルをjsdo.itにアップしておきました。
以下のサンプルを見てもらうとそれぞれがどういう動きをするか分かると思います。

translate関数

translate関数は平行移動をさせる関数です。translate(30px, 40px);と指定すれば、その要素は右に30px、下に40px移動します。
ただし、marginと違いposition: relative; left: 30px; top: 40px;の指定とほぼ同じ動作をします。つまり、移動結果で他の要素に影響を与えることがありません。

rotate関数

rotate関数は回転をさせる関数です。rotate(30deg);と指定すれば、その要素は時計回りに30度(degrees)回転します。
translate関数同様、移動後の結果は他の要素に影響を与えません。

scale関数

scale関数は拡大・縮小をさせる関数です。scale(2, 2);と指定すれば、その要素は縦横ともに2倍に拡大されます。
仮にscale(1, 2);とすれば、縦だけが2倍に拡大されます。
scale関数も他と同様、結果は他要素に影響を与えません。

skew関数

skew関数はせん断する関数です。skew(30deg);と指定すれば、その要素は30度分、せん断されます。実際にどうなるかは上記のサンプルを見てください。
skew関数も結果は他要素に影響を与えません。

関数まとめ

これら関数は単独で使う以外にも、組み合わせて使うこともできます。 回転させた後に拡大、みたいなことがやりたい場合はtrnasform: rotate(30deg) scale(2);とすることでふたつを組み合わせた変形をすることができます。
その他、関数を任意の数指定することでそれぞれの変形を重ねあわせることもできます。

ただしひとつ注意点があります。それは、関数の組み合わせる順番に意味がある、ということです。
詳しくはこの先の行列あたりの話でする予定ですが、移動してから回転させるのか、回転してから移動させるのかで当然結果が変わってきます。
なぜかと言うと、例えばX軸方向に移動させたい場合、rotate関数はX軸自体も回転させてしまうからです。つまり、回転したあとのX軸方向に移動してしまうため結果が変わってしまうのです。
実際のサンプルは以下です。
rotate x translatetranslate x rotateの違いを表しています。

回転の角度は同じで若干分かりづらいので、元の位置を点線で表しています。元の位置からの違いを確かめてみてください。

実は関数は2D用と3D用の2種類

さて、すでにお気づきの人もいるかと思いますが、上で説明していたのは実は2Dに対しての変形でした。
だって、パラメータをふたつしか渡していないですからね。(e.g. translate(30px, 40px))

3Dは3軸に対しての変換なので3つのパラメータが必要です。(XYZ軸ですね)
ただし、上記の関数に単純に3つのパラメータを渡してもダメです。3D用には専用の関数があります。
といっても大した違いはなく、上で説明した関数名の最後に3dをつけるだけです。
つまりtranslate3d(10px, 10px, 10px)という具合です。(この例みたいに3つの値すべてが同じ場合は引数ひとつでも同じ動作になります)

3Dの変換にはパースが必要

さて、実際に3dをつけて変換を行ってみるとおかしなことに気づくと思います。どういうことかと言うと、3Dっぽくない。
なぜ3Dっぽくないのか。理由は、パース(遠近感)がついていないから、です。
遠近感は人が目にするものは(現実世界であれば)すべてに必ずついているものです。遠くのものほど小さく見える、というあれです。

しかし、コンピュータの世界はそれらもしっかりと数値で指定してあげないと解釈ができません。つまり、3Dの指定だけではダメで、ちゃんとパースをどれくらいつけるか、という指定も同時に必要になります。(注意点として、パースの指定は回転を指定した要素の親要素に指定する必要があります)

実際にその違いを以下のサンプルに用意してみました。実際にどれくらい違いがあるのか見てみてください。

並べてみてみるとその違いは一目瞭然ですね。下のほうがより自然に回転しているように見えます。
今回はパースの値を300pxで設定しましたが、この値をいじることで少しまた違った見え方になるので色々いじってみてください。

変換の要、マトリクス

さて、今回はまだ続きます。でもこれが最後です。そして難関です。
最後はマトリクスです。または行列と言います。

マトリクスのむずかしい点は、まずその引数の多さでしょう。2D用のものでも引数は9個、3D用に至っては16個もの数値を指定しないとなりません。
さらに、それぞれの数値は分かりやすい数値にはなっていません。例えば、X軸に対して30度回転させたい、となった場合でも、どこにも30という数字は出てきません。

実際に指定するとmatrix3d(1, 0, 0, 0, 0, 0.8660254, 0.4999999, 0, 0, -0.4999999, 0.8660254, 0, 0, 0, 0, 1)という数値になります。30なんて数字はどこにも出てきていませんね。
なぜこんな複雑な数値を指定する必要があるのでしょうか。それは、これが回転や拡大・縮小、平行移動などの処理をひとまとめにしたものだからです。(上のサンプルは回転ひとつだけですが、いくつも回転や平行移動などを掛けあわせても、指定するのはひとつのマトリクスだけになります)
実際、今回作成したルービックキューブでは、今キューブのそれぞれの面はどこを向いているのか、というのをこのマトリクスを使って表現しました。なぜなら、ユーザの操作によってキューブは常に姿勢が変わってしまいます。その都度、rotateXがいくつで、rotateYがいくつで・・などとやっていたら、style属性に指定する関数があっという間にとんでもない数になってしまいます。

しかし、このマトリクスを使うことで、何回回転されたとしてもひとつのマトリクスでそれを表現することができます。これが、ひとつにまとめられるメリットです。
行列に関しては別で説明しますが、こうした理由からマトリクスを使って姿勢制御をするという選択を取りました。

実際に指定したものは以下になります。
matrix3dに指定する数値の桁を若干省略したので微妙に角度が違いますが、しっかりと数値を指定すれば同じ見た目になります。

まとめ

いかがだったでしょうか。だいぶ基本的なところなので、知っている人が多かったかと思います。
ただ、マトリクスは普段あまり使わないのではないでしょうか。ルービックキューブでは逆にこれを多用しているので、使ったことない人はぜひ、使い方を知って活用してみてください。

だいぶ長くなりましたが、transformについてまとめました。次回は座標変換や行列について書きたいと思います。(CSSまったく関係なくなっちゃいますが・・)

この記事のカテゴリー一覧を見る⇒3D

  • このエントリーをはてなブックマークに追加

トラックバックURL

http://css-eblog.com/cgi-bin/mt/mt-tb.cgi/216