初心者が簡単なメソッドだけでルーレットを作った話

## はじめに
アプリケーションにユニークな機能を付けたいと思い、今日のごはんを決めるためのルーレット機能をHTML+CSS+jQueryで実装しました。
一般的な機能ではないため参考記事も少なく、試行錯誤して実装したので、その過程をアウトプットさせていただきます。

## 作成したルーレット
完成したルーレットはこんな感じです。
加速・減速などはなく回って止まるだけの最低限のルーレットです。
(gif小さくてすみません💦)
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1591612/bcea1be6-8584-ce57-bd05-efa1a2938724.gif)

このルーレットはRailsアプリケーションの一部機能のため、メニュー名は入力フォームからgetメソッドで送った値を表示しています。(フォームが空欄の場合はあらかじめ入れておいたデータからランダムで表示)

## 開発環境
HTML 5
CSS 3
jQuery 3

## 1. HTML・CSSでルーレットの形作り
まずHTMLとCSSで各種ボタン・ポインター・ルーレット盤を作成しました。
( ボタンのデザインやフォーム・メニュー名表示部分は省略しています。)

このルーレットは、色の違う1/4の円を大きな円の上に4つのせ、大きな円を回転させています。

```html:HTML
<div class="buttons">
  <button type="button" id="stop" >ストップ</button>
  <button type="button" id="start">スタート</button>
  <button type="button" id="reset">リセット</button>
</div>

<div id="pointer">▼</div>

<div id="circle">
  <div class="quarter" id="quarter_1"></div>
  <div class="quarter" id="quarter_2"></div>
  <div class="quarter" id="quarter_3"></div>
  <div class="quarter" id="quarter_4"></div>
</div>
```

```css:CSS
.buttons {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}

#pointer {
  text-align: center;
  color: red;
  font-size: xx-large;
  font-weight: bold;
}

#circle {
  height: 400px;
  width: 400px;
  margin: 0 auto;
  border-radius: 50%;
}

.quarter {
  position: absolute;
  top: 0px;
  right: 0px;
  width: 200px;
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
}
#quarter_1 {
  background-color: #bbdbf3;
  border-radius: 0 100% 0 0;
}
#quarter_2 {
  background-color: #e3acae;
  border-radius: 0 0 100% 0;
}
#quarter_3 {
  background-color: #a3d6ce;
  border-radius: 0 0 0 100%;
}
#quarter_4 {
  background-color: #ffedab;
  border-radius: 100% 0 0 0;
}
```

## 2. CSSで回転アニメーションを記述する

```CSS:CSS
.rotate {
  animation: rotate-anime 0.4s linear infinite;
}
@keyframes rotate-anime {
  0%    { transform: rotate(0); }
  100%  { transform: rotate(360deg); }
}
```
初めはjQueryの`animate()`で回転させようと思ったのですが、角度を指定する必要があったため、ストップボタンを押すまで一定速度で回転させるのが難しかったです。
調べていくとCSSの`animationプロパティ`に`infinite`を指定するとアニメーションを無限に繰り返せることが分かり、こちらの方法で実装することにしました。

`@keyframes`を使い、rotate-animeという名前で1回転分のアニメーションを指定し、それを1回転0.4秒、等速で無限に繰り返すようにしています。初期値だと1回転する間に速度が変わってしまう(アニメーションの中央に向けて変化量が増加し、最後に向けて減少)ため`linear`を付けて等速で回転するようにしています。

keyframesについてはこちらの記事を参考にさせていただきました。
[【CSS3】@keyframes と animation 関連のまとめ](https://qiita.com/7968/items/1d999354e00db53bcbd8)

## 3. 各種ボタンをクリックした時の処理を記述する
```css:CSS
.stop {
  animation-play-state: paused;
}
```

```javascript:JavaScript
$(document).on('turbolinks:load', function(){
  var circle       = $("#circle");
  var start_button = $("#start");
  var stop_button  = $("#stop");
  var reset_button = $("#reset");

  //初期状態ではリセットボタンを非表示、ストップボタンをクリック不可にしておく
  reset_button.css("display", "none");
  stop_button.prop("disabled", true);

  // スタートボタンを押した時の処理
  start_button.on("click", function () {
    //スタートボタンをクリック不可、ストップボタンをクリック可能にする
    $(this).prop("disabled", true);
    stop_button.prop("disabled", false);
    //ルーレット盤に .rotate を付与
    circle.addClass("rotate");
  });

  // ストップボタンを押した時の処理
  stop_button.on("click",function () {
    //ルーレット盤に .stop を付与
    circle.addClass("stop");
    //リセットボタンを表示、スタートボタンを非表示にする
    reset_button.css("display", "inline-block");
    start_button.css("display", "none");
  });

  // リセットボタンを押した時の処理
  reset_button.on("click",function () {
    //ルーレット盤から .rotate と .stop を取り除く
    circle.removeClass("rotate");
    circle.removeClass("stop");
    //リセットボタンを非表示、スタートボタンを表示
    reset_button.css("display", "none");
    start_button.css("display", "inline-block");
    //スタートボタンをクリック可、ストップボタンをクリック不可にする
    start_button.prop("disabled", false);
    stop_button.prop("disabled", true);
  });
});
```
回転アニメーションができたら.rotateを付けたり外したりすればOKと思ったのですが、こちらも思い通りに動いてくれませんでした。
ストップボタンを押したときにrotateクラスを外してしまうと、初期位置に戻って回転が停止してしまいます。そのため、回転アニメーションを「一時停止」する必要がありました。
そこで`animation-play-state`というCSSプロパティを使い、値を`paused`とすることで、ストップボタンをクリックしたときに回転の一時停止ができるようになりました。

あとはクラスが余計に付与されないようボタンを制御し、リセットボタンで .rotate と .stop　を取り除く処理をすれば連続でルーレットを回すことが可能になります！

## 最後に

最後までお読みいただきありがとうございました。
かなり無理矢理な機構になってしまいましたが、どうすればルーレットの形や動きにできるだろう？と考えながらコードを書くのは楽しかったです！

フォーム部分やボタンデザインを含めた全記述はGithubに上げています。
https://github.com/terakawaakari/Todays_menu

**ルーレット部分の記述ファイル**
ビュー: Todays_menu/app/views/homes/roulette.html.erb
CSS:  Todays_menu/app/assets/stylesheets/homes.scss
JS:   Todays_menu/app/assets/javascripts/application.js 

もし興味を持っていただけましたら、アプリケーションで是非遊んでみてください！
https://todays-menu.site