また三次元

夕焼け

夕焼けが赤いのは、届く光が赤に偏っているから。 こんな時に虹がかかると、やっぱり赤が強かったりするのだろうか。 いつの日か、単色の虹を見てみたい。

今日も三次元の続き。

css 3D で検索して見つかるサンプルで立方体がよく取り上げられているので、俺も作ってみた。

Front
Back
Left
Right
Top
Bottom

html

<div class="stage smpl1"> <div class="cube"> <div class="face front">Front</div> <div class="face back">Back</div> <div class="face left">Left</div> <div class="face right">Right</div> <div class="face top">Top</div> <div class="face bottom">Bottom</div> </div> </div>

css

:root { --s-f-l: 300px; /* 表示領域の一辺 */ --c-f-l: 180px; /* 立方体の一辺 */ --c-h-l: calc( var( --c-f-l ) / 2 ); } .stage { width: var( --s-f-l ); height: var( --s-f-l ); position: relative; } .cube { width: var( --c-f-l ); height: var( --c-f-l ); position: relative; left: calc( ( var( --s-f-l ) - var( --c-f-l ) ) / 2 ); top: calc( ( var( --s-f-l ) - var( --c-f-l ) ) / 2 ); transform-style: preserve-3d; } .face { width: var( --c-f-l ); height: var( --c-f-l ); position: absolute; left: 0; top: 0; } .face:hover { background-color: rgba( 255, 255, 255, 0.5 ); } .stage .cube .front { transform: translateZ( var( --c-h-l ) ); } .stage .cube .back { transform: rotateY( 180deg ) translateZ( var( --c-h-l ) ); } .stage .cube .left { transform: rotateY( -90deg ) translateZ( var( --c-h-l ) ); } .stage .cube .right { transform: rotateY( 90deg ) translateZ( var( --c-h-l ) ); } .stage .cube .top { transform: rotateX( 90deg ) translateZ( var( --c-h-l ) ); } .stage .cube .bottom { transform: rotateX( -90deg ) translateZ( var( --c-h-l ) ); } .smpl1 { perspective: 500px; } .smpl1 .cube { transform: rotateX( -20deg ) rotateY( 20deg ); }

今回も css はポイントだけ。

前後左右上下の各面で、前は単に前に移動するだけだが、他は回転と移動の組み合わせとなる。

回転と移動などの変換の組み合わせには注意が必要。 詳しい説明が見当たらなかったので推測になるが、変換は、その面のローカル座標系も変換するらしい。 なので、回転してから移動する場合と、移動してから回転する場合とでは、移動の方向を変える必要がある。

例えば右面の場合。

今回の例では、まずY軸周りに90度回転している。 これでローカル座標系も回転するので、この面におけるZ軸は、親空間のX軸と同じになる。 次の移動は、この変換されたローカル座標においての指定となるので、親空間のX方向に動かすために、Z方向を指定するのだな。

.right { transform: rotateY( 90deg ) translateZ( var( --c-h-l ) ); }

逆に先に移動する場合、移動の時点でのローカル座標系は親空間と同じなので、素直にX方向を指定する。 それから回転。 回転がY軸周りに90度なのは同じ。

.right { transform: translateX( var( --c-h-l ) ) rotateY( 90deg ); }

どちらを採用するかは気分次第だが、今回は回転してから移動した。 立方体なので、後で移動した場合、移動を全部同じ形にできるから。 まあ、積極的に推すほどのメリットではないんだけどね。

遠い昔、俺の X68000 がまだ現役だった頃、三次元表現のために同じことをやったなぁ… と、懐かしく思い出した。

ついでに動かしてみた。

Front
Back
Left
Right
Top
Bottom

html

<div class="stage smpl2"> <div class="cube"> … </div> </div>

css

.smpl2 { perspective: 1000px; } .smpl2 .cube { animation: mv2 5s linear infinite; } @keyframes mv2 { 0% { transform: rotateX( 0deg ) rotateY( 0deg ); } 100% { transform: rotateX( 360deg ) rotateY( 360deg ); } }

html も css も上と同じ部分は省略。

ぬるぬる動くワイヤーフレーム立方体を眺めているうちに、時々レンダリングを間違うことに気が付いた。 大体は自然な感じでパースがついているのだが、たまに不自然な台形になる。 どうやら前後を間違っているようで、その間は hover で反応する面も奥の方になる。 暫くすると元に戻る。 俺が設定を間違ってるのではないはず。

さて、動く立方体にはちょっとした満足感があるが、しかし使い道はあんまり無さそうだよな。 hover がちゃんと三次元的に処理されるのは、ゲーム方面で可能性を感じるが。 もっと日常的かつ実用的な用途が何かないか、ちょっと考えてみよう。

続きはまた後日。