こんにちは〜ららぽてすらです♪
今回は、ルーレットの作り方について詳しく解説していきます!
HTML 部分 :
html
<h2> ルーレット </h2>
<p><canvas id="canvas "></canvas ></p>
<div id="labels"></div>
<p><button id="run"> スタート </button> <button id="stop"> ストップ </button></p>
この部分は、ページに表示される HTML のエレメントを定義しています。 <h2> でページのタイトル、 <canvas > で描画するための領域を確保し、 <div> でルーレットの各部分を表すラベルを表示するための領域を確保しています。 <p> で 2 つのボタンを定義し、それぞれルーレットの開始と停止の動作を制御します。
JavaScript 部分 :
const canvas = document.getElementById('canvas '); const context = canvas .getContext('2d'); ここで、 canvas 要素を取得し、 2D 描画コンテキストを取得しています。
var center = { x: 150, y: 150 }; var radius = 100; ここでは、円の中心座標と半径を定義しています。
var data = [ ... ] ここで、ルーレットの各セグメントに対応するデータを定義します。それぞれの名前、色、そして "weight" (このセグメントがルーレットの全体のうち何割を占めるか)が設定されています。
data.forEach(e => { sum_weight += e.weight; }); unit_weight = 360 / sum_weight; ここで、全てのセグメントの weight の合計を計算し、それをもとに 1 単位の weight が何度分に相当するかを計算します。
init(); showLabel(); drawRoullet(0); ここで、描画の初期化、ラベルの表示、そしてルーレットの初期描画を行っています。
function drawRoullet(offset) {...} これはルーレットの描画を行う関数です。オフセットを引数として受け取り、それをもとにルーレットの各セグメントを描画します。
function runRoullet() {...} これはルーレットを動かす関数です。速度と加速度を使ってルーレットの動きをシミュレートしています。
function endEvent(deg) {...} これはルーレットが停止した時の動作を定義した関数です。ルーレットが指しているセグメントを計算し、その結果を表示します。
function init() {...} これは描画の初期化を行う関数です。
function drawPie(cx, cy, start_deg, end_deg, radius , color) {...} これは円の一部(セグメント)を描画する関数です。
function showLabel() {...} これはルーレットの各セグメントのラベルを表示する関数です。
function showArrow() {...} これはルーレットの矢印を表示する関数です。
document.getElementById('run').addEventListener('click', function() {...}); ここで、スタートボタンがクリックされたときの動作を定義しています。
document.getElementById('stop').addEventListener('click', function() {...}); ここで、ストップボタンがクリックされたときの動作を定義しています。
init():
canvas のサイズを設定し、白色で初期化する関数です。
drawPie(cx, cy, start_deg, end_deg, radius , color):
canvas 上に色つきの円の一部(つまり「パイ」)を描画する関数です。中心の位置 (cx, cy) 、開始角度と終了角度( start_deg と end_deg )、半径( radius )、色( color )を指定します。
showLabel():
ルーレットの各セグメントのラベル(つまり、エメラルド、ルビー、ダイヤモンド、サファイア )を HTML テーブルとして生成し、 labels という ID の div 要素に挿入します。
showArrow():
ルーレットの上部に矢印を描画します。これは現在選択されているルーレットセクションを示します。
document.getElementById('run').addEventListener('click', function() {...}):
"run" という ID の要素(スタートボタン)がクリックされたときに runRoullet() 関数を実行します。しかし、これは既にルーレットが開始( startFlag が true )または停止( stopFlag が true )している場合は動作しません。
document.getElementById('stop').addEventListener('click', function() {...}):
"stop" という ID の要素(ストップボタン)がクリックされたときにルーレットの停止を開始します。しかし、これはルーレットが既に開始されていて( startFlag が true )、まだ停止していない( stopFlag が false )場合にのみ動作します。
runRoullet():
ルーレットを回転させるための関数です。加速度を使ってルーレットが回転する度数を計算します。もし stopFlag が true になった場合(つまり、ストップボタンがクリックされた場合)、ルーレットの速度を徐々に減速させます。速度が 0 になると、タイマーをクリアし、 endEvent(deg) 関数を呼び出します。
endEvent(deg):
ルーレットが停止したときに呼び出される関数です。ルーレットが指しているセグメントを計算し、その結果を表示します。また、 startFlag と stopFlag を false にリセットします。
⭐️ルーレットソースコード ⭐️ <p> </p> <style> body { font-family: Arial, sans-serif; text-align: center; background-color: #f4f4f4; }
canvas { border: 2px solid #333; border-radius : 5px; margin-top: 15px; }
button { margin-top: 15px; padding: 10px 20px; font-size: 16px; border: none; border-radius : 5px; cursor: pointer; }
#run { background-color: #4CAF50; color: white; }
#stop { background-color: #f44336; color: white; } </style> <h2>ジュエリーデザインルーレット</h2> <p><canvas id="canvas "></canvas ></p> <div id="labels"></div> <p><button id="run">スタート</button> <button id="stop">ストップ</button></p> <p> <script> const canvas = document.getElementById('canvas '); const context = canvas .getContext('2d');
var center = { x: 150, y: 150, };
var radius = 100;
var data = [{ name: 'エメラルド', color: '#50C878', weight: 1, }, { name: 'ルビー', color: '#E0115F', weight: 1, }, { name: 'ダイヤモンド', color: '#B9F2FF', weight: 1, }, { name: 'サファイア ', color: '#0F52BA', weight: 1, }];
var sum_weight = 0; var unit_weight = 0; var stopFlag = false; var startFlag = false; var timer;
data.forEach(e => { sum_weight += e.weight; }); unit_weight = 360 / sum_weight;
init(); showLabel(); drawRoullet(0);
function drawRoullet(offset) { var uw_count = offset;
data.forEach(e => { drawPie( center.x, center.y, uw_count, uw_count + unit_weight, radius , e.color ); uw_count += unit_weight; }); }
function runRoullet() { var deg = 0; var speed = 0; var acceleration = 0.5;
timer = setInterval(function() { speed += acceleration; deg += speed;
if (deg > 360) { deg = deg % 360; }
if (stopFlag) { acceleration = -0.1; speed += acceleration; if (speed <= 0) { clearInterval(timer); endEvent(deg); } }
context.clearRect(0, 0, canvas .width, canvas .height); drawRoullet(deg); }, 100); }
function endEvent(deg) { var res = ''; var c = deg % 360;
for (var i = 0; i < data.length; i++) { if (unit_weight * i <= c && c < unit_weight * (i + 1)) { res = data[i].name; break; } } startFlag = false; stopFlag = false; }
function init() { canvas .width = 300; canvas .height = 300; var dst = context.createImageData(canvas .width, canvas .height); for (var i = 0; i < dst.data.length; i++) { dst.data[i] = 255; } context.putImageData(dst, 0, 0); }
function drawPie(cx, cy, start_deg, end_deg, radius , color) { var _start_deg = (360 - start_deg) * Math.PI / 180; var _end_deg = (360 - end_deg) * Math.PI / 180; context.beginPath(); context.moveTo(cx, cy); context.fillStyle = color; context.arc(cx, cy, radius , _start_deg, _end_deg, true); context.closePath(); context.lineWidth = 2; context.strokeStyle = '#000'; context.stroke(); context.fill(); showArrow(); }
function showLabel() { var label_el = document.getElementById('labels'); var text = '<table>'; for (var i = 0; i < data.length; i++) { text += `<tr> <td style="width:20px;background-color:${data[i].color};"></td> <td>${data[i].name}</td> </tr>`; } text += '</table>'; label_el.innerHTML = text; }
function showArrow() { context.beginPath(); context.moveTo(center.x, center.y - radius ); context.lineTo(center.x + 10, center.y - radius - 10); context.lineTo(center.x - 10, center.y - radius - 10); context.closePath(); context.stroke(); context.fillStyle = 'rgba(40,40,40)'; context.fill(); }
document.getElementById('run').addEventListener('click', function() { if (!startFlag && !stopFlag) { runRoullet(); startFlag = true; } });
document.getElementById('stop').addEventListener('click', function() { if (startFlag && !stopFlag) { stopFlag = true; } }); </script> </p>
⬇️実際にソース入れた際の表示と動き⬇️
ルーレット
スタート ストップ