JavaScriptでルーレットをつくります。
画像を連続でズラしながら描画することでルーレットが動いているように見せているだけです。簡単にできるので初心者の方にやってみてほしいと思います。
HTML部分
ルーレットの画像が描画される部分だけcanvasを使っています。canvasのまわりにマージンを設定し、ルーレットの背景は黒、画像の背景は白でそれっぽくしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>鳩でもわかるルーレット</title> <meta name = "viewport" content = "width=device-width, initial-scale = 1.0"> <link rel = "stylesheet" href = "./style.css" type = "text/css" media = "all"> </head> <body> <div id = "container"> <canvas id = "canvas"></canvas> <div> <button id = "start" onclick="start()">スタート</button> <button id = "stop" onclick="stop()">ストップ</button> </div> </div> <script src= "./index.js"></script> </body> </html> |
style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
body { background-color: #000; } #container { width: 360px; height: 480px; background-color: #000; } #canvas { margin-left: 100px; margin-top: 100px; } #start, #stop { margin-left: 120px; margin-top: 30px; width: 120px; height: 50px; } |
グローバル変数と定数
JavaScript部分のグローバル変数と定数を示します。
index.js
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 |
const leftMargin = 20; // canvasの左右を20ピクセルあける。とくに意味はない // 画像の幅と高さ const imageWidth = 120; const imageHeight = 120; const $canvas = document.getElementById('canvas'); const ctx = $canvas.getContext('2d'); // スタートボタンとストップボタン const $start = document.getElementById('start'); const $stop = document.getElementById('stop'); // 効果音 const startSound = new Audio('./sounds/start.mp3'); const stopedSound = new Audio('./sounds/stoped.mp3'); // イメージを格納する配列 const images = []; // ルーレットが回転する速度 let speed = 0; const MAX_SPEED = 16; const MIN_SPEED = 4; // ルーレットは停止しているかどうか? let stoped = true; |
ページが読み込まれたときの処理
imagesフォルダのなかに 0.png ~ 5.png の6つがあるという前提で進めます。
まずcanvasのサイズを設定して、画像ファイルを読み込んでイメージを配列のなかに格納します。1番はじめの画像が読み込まれるのを待ってから、それを描画する処理をおこないます。またルーレットが動いていないのにストップボタンが表示されているのはおかしいので非表示にします。
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
window.onload = () => { $canvas.height = imageHeight; $canvas.width = leftMargin + imageWidth + leftMargin; // canvasの幅を画像の幅より広くしているが特に意味は無い // 画像ファイルを読み込んでイメージを配列のなかに格納する for(let i = 0; i < 6; i++){ const image = new Image(); image.src = `./images/${i}.png`; images.push(image); } // 1番はじめの画像が読み込まれるのを待ってから、それを描画する images[0].onload = () => { ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, $canvas.width, $canvas.height); ctx.drawImage(images[0], leftMargin, 0); } $stop.style.display = 'none'; } |
ルーレットを回転させる処理
ルーレットを回転させる処理を示します。
スタートボタンを非表示にしてストップボタンを表示させます。ルーレットが停止しているフラグをクリアしてから回転速度を最大に、回転量を0で初期化します。そしてルーレットが回転しているあいだは0.01秒おきに描画処理をおこないます。
ルーレットの回転速度が最低速度まで下がり、ズレが最低速度より小さい場合はルーレットを止めます。ルーレットが停止しているフラグをセットしてスタートボタンの再表示させます。
ルーレットの回転している場合は2つのイメージをどの位置から描画するかを計算し、その位置に描画する処理をおこないます。そのあと回転総量に回転速度を追加する処理をおこないます。
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 |
async function start(){ // 効果音の再生 startSound.currentTime = 0; startSound.play(); // フラグのクリア stoped = false; // スタートボタンの非表示とストップボタンの表示 $start.style.display = 'none'; $stop.style.display = 'block'; // 回転速度を最大に speed = MAX_SPEED; // 回転総量を0で初期化する let y = 0; // ルーレットが回転しているあいだは0.01秒おきに描画処理をおこなう const id = setInterval(() => { // 回転総量をimageHeightで割り整数部分を取り出せば、どの画像を描画すればよいかがわかる // この数を配列の要素数より小さくするためにimages.lengthの剰余をとる const imageIndex = Math.floor(y / imageHeight) % images.length; // 回転総量をimageHeightで割ったときの剰余がcanvasの一番上からどれだけズレているかがわかる let sy = y % imageHeight; // canvas上部にできる空白には次のイメージを描画する const nextIndex = (imageIndex + 1) % images.length; // ルーレットの回転速度が最低速度まで下がり、ズレが最低速度より小さい場合はルーレットを止める // この場合、イメージはcanvas上部から描画する if(speed <= MIN_SPEED && y % imageHeight < MIN_SPEED){ // 0.01秒おきにおこなわれていた描画処理を停止する stoped = true; sy = 0; clearInterval(id); // スタートボタンの再表示 $start.style.display = 'block'; // ルーレット回転時のBGMの停止 startSound.pause(); setTimeout(() => { // ルーレット停止時の効果音の再生 // 0.25秒待機しているが特に意味はない stopedSound.currentTime = 0; stopedSound.play(); }, 250); } // 描画処理 ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, $canvas.width, $canvas.height); ctx.drawImage(images[imageIndex], leftMargin, sy); ctx.drawImage(images[nextIndex], leftMargin, sy - imageHeight); ctx.lineWidth = 2; ctx.strokeStyle = '#777'; ctx.beginPath(); ctx.moveTo(0, sy); ctx.lineTo($canvas.width, sy); ctx.stroke(); y += speed; }, 10); } |
停止する処理
ルーレットを停止させる処理を示します。
ルーレットは停止ボタンをクリックしたらすぐに停止するのではなく、回転速度がだんだん低下して停止するようにします。停止ボタンがクリックされたら回転速度を半分にしたあと、0.5秒おきに1減らします。これを回転速度が最低速度よりも大きい場合のみ繰り返します。stopedフラグがtrueになっている場合はすでにルーレットは停止しているのでclearInterval関数を呼び出してインターバルを削除します。
1 2 3 4 5 6 7 8 9 10 11 |
function stop(){ $stop.style.display = 'none'; speed /= 2; const id = setInterval(() => { if(speed > MIN_SPEED) speed--; if(stoped) clearInterval(id); }, 500); } |
これ、ルーレットではなくスロットでは?