Javascriptでルーレット作成、円形に要素を配置してルーレットする
- 2021.04.20
- 01_技術ブログ JavaScript
- #Javascript
こんにちは!
dynaです(^^)
この記事は、Javascriptで円周上に要素を配置してルーレットを作成した記録です。
・ルーレット作成の考え方
デモはこちら↓ Resultからスタートボタン押してみてねฅ(ミ・ﻌ・ミ)ฅ
・スタートを再押下でまたルーレットします。(1度ストップしたところはルーレットしない)。
・リセットボタンですべてリセット。
もっといいコードがあると思いますが、とりあえず動いたので記録です。(気になった点や指摘があれば、お問い合わせからお願いします!)
広告
全体のコード
長いので、考え方が気になる方は飛ばしてOKです!
一応全体のコードを載せておきます。
1 2 3 4 5 6 7 8 9 10 11 12 | <body> <div class="display"> <div id = "roulette" class="roulette"></div> <div class="c_button"> <button id ="start">スタート</button> <button id ="stop">ストップ</button> <button id ="reset">リセット</button> </div> </div> </body> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | .display{ margin-top: 100px; margin-left:100px; width: 400px; } .roulette{ display: block; width: 300px; height: 300px; margin: auto; position: relative; } .cil{ width: 80px; height: 80px; background-color: rgb(250, 255, 180); border-radius: 50%;/* 円*/ line-height: 80px; text-align: center; display: block; position: absolute; } .c_button{ width: 600px; top: 100px; margin: auto; position: relative; } button { width: 150px; height: 50px; margin: 20px; border: 2px solid #000; border-radius: 0; background: #fff; text-align: center; } button:hover { color: #fff; background: #000; } .red { background-color:#ff0062; width: 80px; height: 80px; border-radius: 50%;/* 円*/ line-height: 80px; text-align: center; display: block; position: absolute; } .pink{ background-color:#ff73dc; width: 80px; height: 80px; border-radius: 50%;/* 円*/ line-height: 80px; text-align: center; display: block; position: absolute; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | document.addEventListener("DOMContentLoaded", function(){ //要素の表示、円周上に表示させる let num = [0,1,2,3,4,5,6,7,8,9]; //HTMLに表示 let roulette = document.getElementById("roulette"); /*円形に並べる*/ let item_length = num.length; //rouletteの半径を計算 let r = roulette.clientWidth/2; //360度÷配置要素数 let deg = 360.0/item_length; //さっきの角度をラジアンに変更 let rad = (deg*Math.PI/180.0); //要素追加して表示させる for(var i = 0; i < num.length; i++ ){ //div要素の追加 let div = document.createElement('div'); div.className = "cil"; div.id = "cil"+ i; div.innerHTML= num[i] ; const x = Math.cos(rad * i) * r + r; const y = Math.sin(rad * i) * r + r; let circle = roulette.appendChild(div); circle.style.left = x + "px"; circle.style.top = y + "px"; // console.log(x); } //ルーレットする let interval;//インターバル let first = false;//フラグ let number = 1; let grid =0; function start_set(){//start状態 document.getElementById("start").disabled = true; document.getElementById("stop").disabled = false; document.getElementById("reset").disabled = false; if(first === false){ interval = setInterval(start_go,100); first = true; } } function start_go(){//start押下 for(var k = 0; k < item_length; k++){ let div_number = document.getElementById('cil'+[k]);//表示上のidの取得 div_number.classList.remove('red');//.redを消す } grid = Math.floor(Math.random()*num.length); number = num[grid];//.redをつけるためのランダムな数字を選択 div_number = document.getElementById('cil'+ number); //console.log(div_number); div_number.classList.add('red'); } function stop_set(){//stop押下 document.getElementById("stop").disabled = true; document.getElementById("start").disabled = false; clearInterval(interval); first = false; let red_number = document.querySelector('.red');//.redクラスのついているものを取得 //console.log(grid); num.splice(grid,1);//配列からred_numberのところを1つ削除 //console.log(num); red_number.classList.remove('red'); red_number.classList.add("pink"); if(num.length === 0){ document.getElementById("start").disabled = true; } } function reset_set(){//リセット押下 clearInterval(interval); first = false; document.getElementById("start").disabled = false; for(var j = 0; j < 10 ; j++){ let all = document.getElementById("cil" + j); all.classList.remove('pink'); all.classList.remove('red'); } num = [0,1,2,3,4,5,6,7,8,9]; } const starter = document.getElementById("start"); const stopper = document.getElementById("stop"); const resetter = document.getElementById("reset"); starter.addEventListener("click",start_set,false); stopper.addEventListener("click",stop_set,false); resetter.addEventListener("click",reset_set,false); document.getElementById("stop").disabled = true; document.getElementById("reset").disabled = true; }) |
まずは円周上に要素を配置するところから。
Javascriptで円形(円周上)に要素を配置
地味に難しかった・・・。
参考にさせていただいたサイトはこちら↓
考え方としては以下の順で考えました。
- (1)要素をJSで表示させるので、表示させたい枠(div)を取得
- (2)表示する要素数を決める(ここでは10個)
- (3)円周上に配置したいので(1)(表示枠)の半径を算出する
- (4)円周上に配置するので、360度÷(2)(配置する要素数)をする
- (5)CSS操作できるように、(4)をラジアンに変換する
- (6)要素を表示する
- (6)-1.エレメントの追加(class,idの追加)、(6)-2.x,y座標の追加
※下記コードに対応個所を()数字で振っています。
円周上に要素を配置するコードはこちら↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | //要素の表示、円周上に表示させる(2) let num = [0,1,2,3,4,5,6,7,8,9]; //HTMLから取得(1) let roulette = document.getElementById("roulette"); /*円形に並べる手順*/ let item_length = num.length; //rouletteの半径を計算(3) let r = roulette.clientWidth/2; //360度÷配置要素数(4) let deg = 360.0/item_length; //さっきの角度をラジアンに変更(5) let rad = (deg*Math.PI/180.0); //要素追加して表示させる(6) for(var i = 0; i < num.length; i++ ){ //div要素の追加(6-1) let div = document.createElement('div'); div.className = "cil"; div.id = "cil"+ i; div.innerHTML= num[i] ; //(6-2) const x = Math.cos(rad * i) * r + r; const y = Math.sin(rad * i) * r + r; let circle = roulette.appendChild(div); circle.style.left = x + "px"; circle.style.top = y + "px"; // console.log(x); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | .display{ margin-top: 100px; margin-left:100px; width: 400px; } .roulette{ display: block; width: 300px; height: 300px; margin: auto; position: relative; } .cil{ width: 80px; height: 80px; background-color: rgb(250, 255, 180); border-radius: 50%;/* 円*/ line-height: 80px; text-align: center; display: block; position: absolute; } .c_button{ width: 600px; top: 100px; margin: auto; position: relative; } button { width: 150px; height: 50px; margin: 20px; border: 2px solid #000; border-radius: 0; background: #fff; text-align: center; } button:hover { color: #fff; background: #000; } |
先ほどの「考え方」の「(6)-2、要素を追加して、x、y座標に設定する」ところが躓いたので、そちらをメモしておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //要素追加して表示させる(6) for(var i = 0; i < num.length; i++ ){ //(2)のnumの要素の数だけforで回す //div要素の追加(6-1) let div = document.createElement('div'); //divを作る div.className = "cil"; div.id = "cil"+ i; div.innerHTML= num[i] ; //(6-2) const x = Math.cos(rad * i) * r + r; const y = Math.sin(rad * i) * r + r; let circle = roulette.appendChild(div);//要素を(1)の表示部分へ追加する circle.style.left = x + "px"; //ここで表示位置を指定する x、y軸 circle.style.top = y + "px"; // console.log(x); } |
気になるのが
const x = Math.cos(rad * i) * r + r;
const y = Math.sin(rad * i) * r + r;
sin,cos(サインコサイン)って昔勉強したなあ・・・
もう覚えてない( ^ω^)・・・
このサイトが分かりやすかったです。
Mathオブジェクトのcos()メソッドは、コサイン(余弦)を返します。 引数にラジアン単位の角度を指定すると、指定した引数のコサイン(余弦)を返します。
引用元:★JavaScriptリファレンス Math.cos() …… コサイン(余弦)を返す
デモコードのラジアン計算しているところが、
let deg = 360.0/item_length;
let rad = (deg*Math.PI/180.0);
に当たります。
これを元に考えると、上記のコードはradの変数にラジアン計算をしているので、
const x = Math.cos(rad * i) * r + r; は
const x = Math.cos(rad * 要素が何個めか) * 半径 + 半径;
ということになります。
これで、要素のiが変化して、円周上のx(コサイン)、y(サイン)で要素数分位置を算出してくれます。
このx、yの値を、トップから〇px、左に〇px、とずらして表示しています。
なんとなく分かったけど、使いこなすの難しいね・・・(;’∀’)
ルーレット作成の考え方
先ほどの円周上に要素を作ることで表示ができたので、次はルーレットを作成します。
- スタート準備状態(stert_set)、スタートボタン押下時(start_go)、ストップボタン押下時(stop_set)、リセットボタン押下時(reset_set)で考える
- 1.スタートボタン押下時
・・・表示している要素をランダムに選び、背景色を表示するクラスを付与する。 - 2.ストップボタン押下時
・・・現在選択しているランダムな数字を取得し、ストップの背景色を付与する。また、選んだものを元の配列から減らす。 - 3.リセットボタン押下で色のクリア(初期化)、配列のクリア(初期化)
- スタート準備状態で、スタートボタン押下時の実行処理のタイミングを設定する
- スタート、ストップ、リセットのボタンを取得
- それぞれ押下時のクリックイベント処理の追加をする
ちょっとしたポイントは、フラグ処理 (let first )で制御していることです。
「スタート準備状態時(start_set)にfirst===falseならスタートボタン押下処理を、一定の間隔で実行する」
としています。
あとはコードにメモがあるので、それを見ればやっていることは単純なので、なんとなく分かります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | //ルーレットする let interval;//インターバル let first = false;//フラグ let number = 1; let grid =0; function start_set(){//start状態 document.getElementById("start").disabled = true; document.getElementById("stop").disabled = false; document.getElementById("reset").disabled = false; if(first === false){ interval = setInterval(start_go,100); first = true; } } function start_go(){//start押下 for(var k = 0; k < item_length; k++){ let div_number = document.getElementById('cil'+[k]);//表示上のidの取得 div_number.classList.remove('red');//.redを消す } grid = Math.floor(Math.random()*num.length); number = num[grid];//.redをつけるためのランダムな数字を選択 div_number = document.getElementById('cil'+ number); //console.log(div_number); div_number.classList.add('red'); } function stop_set(){//stop押下 document.getElementById("stop").disabled = true; document.getElementById("start").disabled = false; clearInterval(interval); first = false; let red_number = document.querySelector('.red');//.redクラスのついているものを取得 //console.log(grid); num.splice(grid,1);//配列からred_numberのところを1つ削除 //console.log(num); red_number.classList.remove('red'); red_number.classList.add("pink"); if(num.length === 0){ document.getElementById("start").disabled = true; } } function reset_set(){//リセット押下 clearInterval(interval); first = false; document.getElementById("start").disabled = false; for(var j = 0; j < 10 ; j++){ let all = document.getElementById("cil" + j); all.classList.remove('pink'); all.classList.remove('red'); } num = [0,1,2,3,4,5,6,7,8,9]; } const starter = document.getElementById("start"); const stopper = document.getElementById("stop"); const resetter = document.getElementById("reset"); starter.addEventListener("click",start_set,false); stopper.addEventListener("click",stop_set,false); resetter.addEventListener("click",reset_set,false); document.getElementById("stop").disabled = true; document.getElementById("reset").disabled = true; |
やりたい処理を、分けて考えるの難しいよね~
こればっかりは練習が必要だね( ^ω^)・・・
「どう組み立てたら動くか」の考え方が大事だなーと思った学習でした。
やりたい事をできるようにする為に、今後も勉強していきたいと思います!!
ここまで読んで下さりありがとうございます。
<参考本>
<あわせて読みたい>