Little Strange Software

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

【CSS/JavaScript】立体サイコロ、完成!

f:id:little_strange:20211125233725p:plain

 

 どうも!LSSです!!

 

【CSSお絵描き】サイコロの目を描いてみよう - Little Strange Software

で、サイコロのデザインが完成していました。

 

今回はいよいよ、そのサイコロを振って遊べるバージョンの公開です^^

 

 

サイコロをクリックまたはタップしてください

 

 

 
 
 
 
 
 

 

 

 

※以下、「コード」や「コード解説」が長々と続きます。
 興味のない方は「あとがき」まで読み飛ばしてください^^;

 

 

コード

<style>
.cb01{
position:relative;
transform-style:preserve-3d;
width:150px;
height:150px;
left:75px;
transition:1.5s;
transform:rotateX(-10deg) rotateY(-10deg) rotateZ(0deg);
}
.cb01 div{
position:absolute;
box-sizing:border-box;
width:100%;
height:100%;
border-radius:5px;
border:3px solid #ddddddc0;
background-color:#ccffccdd;
}
.cbs1{
background-image:
radial-gradient(circle at 50% 50%,#ff0000ff 19%,#ff000000 20%);
transform:translateZ(75px);
}
.cbs2{
background-image:
radial-gradient(circle at 75% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 25% 75%,#000000ff 10%,#00000000 11%);
transform:rotateY(90deg) translateZ(75px);
}
.cbs3{
background-image:
radial-gradient(circle at 75% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 50% 50%,#000000ff 15%,#00000000 16%)
,radial-gradient(circle at 25% 75%,#000000ff 10%,#00000000 11%);
transform:rotateX(90deg) translateZ(75px);
}
.cbs4{
background-image:
radial-gradient(circle at 25% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 25% 75%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 75% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 75% 75%,#000000ff 10%,#00000000 11%);
transform:rotateX(-90deg) translateZ(75px);
}
.cbs5{
background-image:
radial-gradient(circle at 25% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 25% 75%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 50% 50%,#000000ff 15%,#00000000 16%)
,radial-gradient(circle at 75% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 75% 75%,#000000ff 10%,#00000000 11%);
transform:rotateY(-90deg) translateZ(75px);
}
.cbs6{
background-image:
radial-gradient(circle at 25% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 25% 50%,#000000ff 12%,#00000000 13%)
,radial-gradient(circle at 25% 75%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 75% 25%,#000000ff 10%,#00000000 11%)
,radial-gradient(circle at 75% 50%,#000000ff 12%,#00000000 13%)
,radial-gradient(circle at 75% 75%,#000000ff 10%,#00000000 11%);
transform:rotateY(180deg) translateZ(75px);
}
</style>
<div id="cbid" class="cb01">
<div class="cbs1"> </div>
<div class="cbs2"> </div>
<div class="cbs3"> </div>
<div class="cbs4"> </div>
<div class="cbs5"> </div>
<div class="cbs6"> </div>
</div>
<p>
<script>
cbrtt=[
'rotateX(-10deg) rotateY(-10deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(-100deg) rotateZ(0deg)',
'rotateX(-100deg) rotateY(0deg) rotateZ(-10deg)',
'rotateX(80deg) rotateY(0deg) rotateZ(10deg)',
'rotateX(-10deg) rotateY(80deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(170deg) rotateZ(0deg)'
];
cbid.addEventListener('click',
 function(){
  cbid.style.transform='rotateX('+(800+200*Math.random())+'deg) rotateY('+(50+100*Math.random())+'deg) rotateZ('+(50+100*Math.random())+'deg)';
  setTimeout(function(){
   cbid.style.transform=cbrtt[Math.floor(Math.random()*6)];
  },1500);
 }
,false);
</script>

 

 

コード解説(CSS部分)

まずCSSの指定で、@keyframesをざっくり削除しました。

 

次にanimationプロパティも削除し、

transition:1.5s;
transform:rotateX(-10deg) rotateY(-10deg) rotateZ(0deg);

に置き換えています。

 

animationの代わりとなるのが「transition:1.5s;」で、これは「スタイル指定に変化があった時、1.5秒かけて徐々に変化するように」という指定です。
※変化にかける時間1.5s以外の指定を省略しているので、変化タイミングはデフォルトのease、回数は1回となります。

 

そして、最初は「1」の面が向くようにtransformでrotateを設定しています。

 

 

コード解説(JavaScript部分)

JavaScript部分のコード

<script>
cbrtt=[
'rotateX(-10deg) rotateY(-10deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(-100deg) rotateZ(0deg)',
'rotateX(-100deg) rotateY(0deg) rotateZ(-10deg)',
'rotateX(80deg) rotateY(0deg) rotateZ(10deg)',
'rotateX(-10deg) rotateY(80deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(170deg) rotateZ(0deg)'
];
cbid.addEventListener('click',
 function(){
  cbid.style.transform='rotateX('+(800+200*Math.random())+'deg) rotateY('+(50+100*Math.random())+'deg) rotateZ('+(50+100*Math.random())+'deg)';
  setTimeout(function(){
   cbid.style.transform=cbrtt[Math.floor(Math.random()*6)];
  },1500);
 }
,false);
</script>

 

あとはJavaScript任せとなりますが、大きく分けると2つの処理に分けられます。

 

  • 配列変数にサイコロ6面の「向き」を設定
  • サイコロ自体に「クリック時に回転して最終的にサイコロ6面のうちどれかになる」というイベントリスナーを設定

の2つです。

 

配列変数の設定

cbrtt=[
'rotateX(-10deg) rotateY(-10deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(-100deg) rotateZ(0deg)',
'rotateX(-100deg) rotateY(0deg) rotateZ(-10deg)',
'rotateX(80deg) rotateY(0deg) rotateZ(10deg)',
'rotateX(-10deg) rotateY(80deg) rotateZ(0deg)',
'rotateX(-10deg) rotateY(170deg) rotateZ(0deg)'
];

この部分ですね。

「cbrtt」と名付けた配列変数に、6つの文字列を代入しています。

これが、後でJavaScriptからサイコロのCSSプロパティ「transform」に代入する6つの面の設定となります。

例えば一つ目の、

'rotateX(-10deg) rotateY(-10deg) rotateZ(0deg)',

は、先にCSS部分の解説にあった、

transform:rotateX(-10deg) rotateY(-10deg) rotateZ(0deg);

と同一の内容となっているわけです。

 

イベントリスナーの設定

cbid.addEventListener('click',
 function(){
  cbid.style.transform='rotateX('+(800+200*Math.random())+'deg) rotateY('+(50+100*Math.random())+'deg) rotateZ('+(50+100*Math.random())+'deg)';
  setTimeout(function(){
   cbid.style.transform=cbrtt[Math.floor(Math.random()*6)];
  },1500);
 }
,false);

この部分です。

 

サイコロにクリックイベントのイベントリスナー(クリックされた時に処理を実行するための監視)を設定しています。

今回はイベントリスナーの中に、行う処理をまるっと書き、さらにその中にタイマーをセットしつつ、その中にまた行う処理をまるっと書く、という無謀な(?)事をやってます^^;

 

やりたい事は

  • クリックされた時、まず上のほうに向かって回転をするようにtransformを設定(回転量はランダム要素を含めて到達点での角度が常に違うようにする)、
  • それから「1.5秒後に発動するタイマー」を仕掛け、
  • 1.5秒後には「1」~「6」のどれかの面になるように再度transformを設定する。

という事を行おうとしています。

先にCSSのほうでtransitionを1.5秒で設定しているため、アニメーションはCSS任せとなり、JavaScriptからは「変化後の値」を指定するだけで回転アニメーションしてくれる事になります^^

 

クリックイベントを監視させる場合のイベントリスナーの書式は、

対象となる要素id.addEventListener('click',処理内容,false);

で仕込む事ができます。

「処理内容」の部分に関数名を書くと、その関数を呼び出してくれる事になりますが、関数名ではなく、

function(){処理}

を書くと関数を用意しなくても「処理」の内容を実行してくれる事になります。

対象となる要素id.addEventListener('click',function(){処理},false);

という形式ですね。

 

そしてその「処理」の中に、

  cbid.style.transform=
'rotateX('+(800+200*Math.random())+'deg)
 rotateY('+(50+100*Math.random())+'deg)
 rotateZ('+(50+100*Math.random())+'deg)';

と、

  setTimeout(function(){
   cbid.style.transform=cbrtt[Math.floor(Math.random()*6)];
  },1500);

を記述しました。

 

前者が「とりあえず最初は上の方に回転させる」という処理、後者は「1500ミリ秒(=1.5秒)後に、サイコロが結果となる面を向くようにさせる」という内容です。

 

これらの指定により、

  • まずは上の方に回転した状態に1.5秒(CSSのtransitionの指定による)かけて変化する
  • 変化し始めてからの1.5秒後(JavaScriptのsetTimeoutの指定による)に今度はサイコロの結果となる面への変化が指定され、これまた1.5秒(CSSのtransitionの指定による)かけて変化する

という事になります。(つまり、クリックしてから結果の面が出るまで合計3秒かかります)

 

 

あとがき

途中、「上の方に回転」を挟まないと、「1の目から1の目の時に微動だにしない」事になり、クリックできたんだかできなかったんだか分からない、という事になるのでどうしたものか?

と考えた結果、こんな感じになりました。

 

あとは…クラス名やidを書き換えて、サイドバーのサイコロを置き換えてみようかな^^

 

 

 

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

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