今回のお題は、5つの画像で五角柱を組み立てて、水平に回してみよう(サンプル1)。五角柱にマウスポインタを重ねれば、回転は止まる。ずっと回し続けるために、アニメーションにはanimation
プロパティを使った。といっても、設定そのものはさほどむずかしくない。考え方さえわかれば、3次元のアニメーションは「こけおどし」にはもってこいといえる。
五角柱をつくる計算
今回の表現は、「Photos on a rotating polygon」を採り入れた。もちろん、コードはわかりやすいように大幅に書き替えてある。画像を回す前に、まず五角柱を組み立てなければならない。そのために使うのは、座標変換のtransform
プロパティだ。関数rotateY()
とtranslateZ()
で、5つの画像を順に垂直軸で回しては移動する。まずは、わかりやすいように、四角柱で考え方を確かめておこう。
四角柱は、4つの側面がそれぞれ隣の面と直角に接する(上面と底面はなしとする)。配置を確かめるためには、真上から見たxz平面で考えるとよい(図1)。z軸の下方向が、画面に向かって正面だ。ひとつめの面を、まずy軸で90度回す(rotateY()
関数)。すると、面のxz軸も一緒に90度回転する。そこでつぎに、面のz軸方向にその幅の半分動かせばよい(translateZ()
関数)。なお、座標変換では、複数の変換を加えた場合、一般にその順序によって結果は変わるので注意してほしい。
五角柱もそれぞれの面をy軸で回して(rotateY()
関数)、z軸の向きに位置を変える(translateZ()
関数)ことは同じだ(図2)。ただし、回転角は72度(= 360 / 5)ずつになる。このとき、z軸方向にどれだけ動かせばよいか。四角柱のように、面の幅の半分と、たやすくは計算できない。
この場合、三角関数のtanを使う。tanはつぎのように定められている(図3)。一般に、直角三角形の直角でない角(θ)と1辺がわかれば、他の辺は三角関数を用いた比例計算で導ける(斜辺が得られたときにはsinまたはcosを使う)。
さて、五角柱の場合は、角度θは36度(= 72 / 2)だ。HTMLドキュメントの<body>
要素の記述は以下のコード1のとおりで、5つの画像(img
要素)の幅(width
プロパティ)は<img>
要素に揃えて240ピクセルを与えたので、その半分は120ピクセルとなる。すると、各面をz軸方向に動かす長さtzは、つぎのように求められる。
もっとも、tan(36°)をどうやって計算するか、不安を感じた読者もいるかもしれないが難しくはない。ブラウザのコンソールを使って、JavaScriptで求めればよい(Google Chromeなら[表示]/[開発/管理]/[JavaScriptコンソール])。JavaScriptでtanの値はMath.tan()
メソッドにより得られる。ただし、引数に渡す角度は度数でなくラジアンを単位とする。180度がπラジアンなので、36度はπ / 5ラジアンだ。πの値はMath.PI
定数で表される。コンソールにつぎのように入力したら、移動する長さは約165ピクセルだとわかった(図4)。
五角柱を組み立てる
それでは、5つの画像で五角柱を組み立てよう。前掲コード1に対して、3次元の操作やアニメーションを加える前に、つぎのようなCSSを定めた。
3次元の表現を加えるには、プロパティtransform-style
にpreserve-3d
を与え、perspective
の値が定められていなければならない(第4回の「要素にポインタを重ねたら水平軸で回す」参照)。そのうえで、つぎのように各面のクラス(face-1~face-5)にそれぞれの面の角度と移動の位置決めをした。なお、0度の回転はデフォルトなので省いて構わない。
面のz軸方向の位置は少し遠め(175ピクセル)にした。各面の両端に少し余白をとった方が、背後の面も透けて立体感が増すからだ。そのため、padding
プロパティに左右の余白を定めた[1]。
これで、5つの画像で五角柱ができ上がる(図5)。ここまでのCSSの定めをコード2にまとめた。
五角柱を水平に回す
いよいよアニメーションを定める。もっとも、このお題でややこしいのは、前項までに行った面の位置決め計算だ。プロパティanimation
の使い方は、基本がtransition
と同じで、それに少し付け加えるだけといえる。つぎのように、時間とタイミング関数はtransition
と変わらない。繰り返し回数が与えられるのは、animation
プロパティのよいところだ。繰り返し続けたいときは、値をinfinite
とする。一番の違いは、任意のアニメーション名を定めなければならないことである。
今回は、以下のようにanimation
プロパティを指定した。タイミング関数linear
は、時間に対して値が線形で変わる。
アニメーション名は@keyframes
規則に与える。transition
プロパティは、始めと終わりのプロパティを定めると、その間をアニメーションした。@keyframes
規則には、いくつでも経過点が加えられる。この経過点を「キーフレーム」と呼び、始めを0%、終わりを100%とするパーセンテージで与える。始めと終わりは、それぞれfrom
およびto
というキーワードを用いてもよい。
もっとも今回は、決まった速さで回り続けるだけなので、つぎのように始めと終わりだけ定めれば足りる。さらにいえば、始めのプロパティはデフォルトの状態なので省いて構わない。
アニメーションのために加えたコードがあっけないほど簡単だったので、もうひとつ書き足すことにしよう。五角柱にマウスポインタを重ねたら、回転を止める。そのときに使うのが、animation-play-state
だ。つぎのように、値にpaused
を与えるとアニメーションは一時停止する。デフォルト値は、アニメーションを実行するrunning
になっている。書き上がったCSSの定めは、以下のコード3にまとめた。