Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

【CSS】preserve-3dを使って直方体を描いてみたら案の定大変だった話

 どうも!LSSです!!

 

以前、

little-strange.hatenablog.com

で、CSSで立体的な立方体を描いてみました。

 

その際に、

…ただし、位置決めなどの指定がとても複雑で、例えば今回は立方体でしたが、これを直方体にしようと思っただけでも話がややこしくなりそうです^^;

【CSS】サイコロ回転【preserve-3d試してみた】 - Little Strange Software

と書いていましたが、実際に直方体を描こうとしたら結構迷ってしまいました^^;

が、なんとか描けました^^

 

 

幅200px高さ100px厚さ20pxの直方体

 

 
 
 
 
 
 

 

 

コード

<style>
.box3d{
position:relative;
transform-style:preserve-3d;
width:200px;
height:100px;
transform:rotateX(-20deg) rotateY(-20deg);
}
.box3d div{
position:absolute;
box-sizing:border-box;
border:1px solid #000000;
}
.box3dfront{
width:200px;
height:100px;
background-color:#ffffccdd;
transform:translateZ(10px);
}
.box3dback{
width:200px;
height:100px;
background-color:#ffffccdd;
transform:rotateY(180deg) translateZ(10px);
}
.box3dright{
width:20px;
height:100px;
background-color:#ffccccdd;
transform:rotateY(90deg) translateZ(190px);
}
.box3dleft{
width:20px;
height:100px;
background-color:#ffccccdd;
transform:rotateY(-90deg) translateZ(10px);
}
.box3dtop{
width:200px;
height:20px;
background-color:#ccffccdd;
transform:rotateX(90deg) translateZ(10px);
}
.box3dbottom{
width:200px;
height:20px;
background-color:#ccffccdd;
transform:rotateX(-90deg) translateZ(90px);
}
</style>
<div class="box3d">
<div class="box3dfront"> </div>
<div class="box3dback"> </div>
<div class="box3dright"> </div>
<div class="box3dleft"> </div>
<div class="box3dtop"> </div>
<div class="box3dbottom"> </div>
</div>

 

 

各面の描画の起点は左上、回転の中心は各面の中心

である事を意識しないと、立方体の時は全て同じように重なっていたので問題なくいけましたが、直方体となると計算がひどくややこしくなりました^^;

box3dfrontは手前の面、box3dbackはその反対側となる背面、同rightは右側面、同leftは左側面、同topは天面、同bottomは床面、という風にclass名を命名しています。

 

それで幅200px、高さ100px、厚さ20pxの直方体を組み立てようとすると、frontとbackは

width:200px;
height:100px;

となり、右側面と左側面は

width:20px;
height:100px;

となり、天面と床面は

width:200px;
height:20px;

となります。

 

そして、これらの立体として組み立てる前の配置は、

 
 
 
 
 
 

↑こういう配置になるんですね。
(全体となる長方形が手前面と背面、左端にある縦長の直方体が右側面と左側面、上端にある横長の長方形が天面と床面になります。)

 

ここから立体的に組み立てようとすると、例えば右側面は、

.box3dright{
width:20px;
height:100px;
background-color:#ffccccdd;
transform:rotateY(90deg) translateZ(190px);
}

まず、rotateY(90deg)で90度傾けます。
幅20pxの中心から、縦軸を中心として回転させる事になるので、位置的には左から10pxの位置の縦線となり、それを左から200pxの位置に配置させないとなので…

translateZ(190px)によって「あらかじめ190px手前に引っ張り出してきてから、回転させる事で、200px(10+190)右の位置に収まる」という計算になります。

 

これが左側面の場合は、

.box3dleft{
width:20px;
height:100px;
background-color:#ffccccdd;
transform:rotateY(-90deg) translateZ(10px);
}

まずrotateY(-90deg)で先ほどと反対方向に縦軸を中心に90度傾けますが、やはり幅20pxの中心が軸となるので、左から10pxの位置の縦線となるので…

translateZ(10px)によって「あらかじめ10px手前に引っ張り出してきてから(略)」という計算になります。

 

天面・床面に置いても、縦軸回転→横軸回転に置き換えて同様の計算を行う事になります。

.box3dtop{
width:200px;
height:20px;
background-color:#ccffccdd;
transform:rotateX(90deg) translateZ(10px);
}
.box3dbottom{
width:200px;
height:20px;
background-color:#ccffccdd;
transform:rotateX(-90deg) translateZ(90px);
}

 

 

あとがき

立方体の場合には正方形相手だったので「向きだけ変えて同じように回転させる」事で作れていましたが、直方体になると急に話がややこしくなりましたね^^;

 

今回描いてみた時も最初「中心が中心」という考え方をしてしまって思い通りに行かず、頭を悩ませる事になりました^^;;;

 

当初予測した以上にややこしく、今回の記事でも説明しきれていないと思いますが、なんとか自分が描けるところまで辿りついたので、JavaScriptに頼って「幅・高さ・厚さを指定して直方体CSSを出力するコード生成ツール」でも作ってみようかな?とか思う今日この頃です。

あ、CSS変数とcalc関数を使うという手でもいいのかも?

 

 

 

ってなとこで、今回はこのへんで!

次回もまた、よろしくお願いします^^