【JavaScript】Rythm.jsで音に合わせて画像を躍らせてみた

# はじめに

こんにちは、エンジニアのkeitaMaxです。

今回は、Rythm.jsというJavaScriptのライブラリを使ってみようと思います。

公式サイトは以下のURLです。

https://okazari.github.io/Rythm.js/


# 音に合わせて画像を躍らせてみる


CDNがあるので、それをheadタグ内に入れます。

```html
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script src="https://unpkg.com/rythm.js/"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rythm.js/2.2.5/rythm.min.js"></script>
</head>
```

躍らせたい画像をどこからか持ってきて、htmlのbodyを以下のようにします。
```html
<body>
    <div class="rythm_area">
      <div class="rythm">
        <img src="note.png" />
      </div>
      <button id="music_start_button">スタート！</button>
      <button id="music_stop_button">ストップ</button>
    </div>
    <script src="main.js"></script>
</body>
```

スタートボタンを押すと音楽が流れ、ストップボタンを押すと止まるようにします。また、音楽がなっている間だけ画像が躍るようにしてみます。

JavaScriptは以下のようにしてみました。
```javascript:main.js
var rythm;
var isStart = false;

(function () {
  rythm = new Rythm();
  rythm.addRythm("music_dance", "music_dance", 0, 10, { direction: "left" });

  music();
})();

function music() {
  document
    .getElementById("music_start_button")
    .addEventListener("click", function (e) {
      if (isStart) {
        return;
      }
      initRythm();
      addRythmClass(this);
      rythm.setMusic("sample.mp3");
      rythm.start();
      isStart = true;
    });
  document
    .getElementById("music_stop_button")
    .addEventListener("click", function (e) {
      initRythm();
    });
}
function initRythm() {
  Array.from(document.getElementsByClassName("rythm")).forEach((element) => {
    element.classList.remove("music_dance");
  });
  rythm.stop();
  rythm.setMusic("");
  isStart = false;
}

function addRythmClass(e) {
  e.closest(".rythm_area")
    .getElementsByClassName("rythm")[0]
    .classList.add("music_dance");
}
```


スタートボタンを押したときに、躍らせたい画像にmusic_danceというクラスを付与し、ストップボタンを押したときにmusic_danceというクラスを除去するように処理を作成しました。

これは、押したボタンによって躍らせる画像を選択するために今回はこのような実装になっています。

作成したJavaScriptにブラウザでアクセスをすると、選んだ画像とボタンが表示されます。

スタートボタンを押すと画像が躍り始めます。

ここで注意しなくてはならないのが、ボタンを押さずに音楽を流そうとするとエラーになってしまう点です。

これはChromeの仕様で、ボタンをクリックするなどのアクションを取らせてから出ないと音を流すことができないらしいです。

### 今回使用した画像と音声

使用した画像は以下のフリーの画像サイトからダウンロードしました。
https://icooon-mono.com/

音楽は以下のサイトからダウンロードしました。
https://dova-s.jp/

# マイクから拾った音を利用して自分の声で画像を躍らせる

先ほどのJavaScriptを修正して、マイクの音を拾って画像を躍らせることをやってみます。

先ほどのhtmlに以下を追加します。

```html
<div class="rythm_area">
      <div class="rythm">
        <img src="note.png" />
      </div>
      <button id="mic_start_button">スタート！</button>
      <button id="mic_stop_button">ストップ</button>
</div>
```
また、Javascriptには以下を追加します。
```javascript
function mic() {
  document
    .getElementById("mic_start_button")
    .addEventListener("click", function (e) {
      if (isStart) {
        return;
      }
      initRythm();
      addRythmClass(this);
      rythm.plugMicrophone();
      isStart = true;
      rythm.start();
    });

  document
    .getElementById("mic_stop_button")
    .addEventListener("click", function (e) {
      initRythm();
    });
}
```
この関数をJavascript読み込み時に読み込んであげるように以下のように修正します。

```javascript
(function () {
  rythm = new Rythm();
  rythm.addRythm("music_dance", "music_dance", 0, 10, { direction: "left" });

  music();
  mic();
})();
```
これでブラウザでアクセスをして、今回作成したスタートボタンを押すと、マイクの音を拾ってそれによって画像が躍り始めます。

# 今回作成したソースコード

最後に今回作成したソースコードを載せておきます。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script src="https://unpkg.com/rythm.js/"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rythm.js/2.2.5/rythm.min.js"></script>
  </head>
  <body>
    <div class="rythm_area">
      <div class="rythm">
        <img src="note.png" />
      </div>
      <button id="music_start_button">スタート！</button>
      <button id="music_stop_button">ストップ</button>
    </div>
    <div class="rythm_area">
      <div class="rythm">
        <img src="note.png" />
      </div>
      <button id="mic_start_button">スタート！</button>
      <button id="mic_stop_button">ストップ</button>
    </div>
    <script src="main.js"></script>
  </body>
</html>
```

```javascript:main.js
var rythm;
var isStart = false;

(function () {
  rythm = new Rythm();
  rythm.addRythm("music_dance", "music_dance", 0, 10, { direction: "left" });

  music();
  mic();
})();

function music() {
  document
    .getElementById("music_start_button")
    .addEventListener("click", function (e) {
      if (isStart) {
        return;
      }
      initRythm();
      addRythmClass(this);
      rythm.setMusic("sample.mp3");
      rythm.start();
      isStart = true;
    });
  document
    .getElementById("music_stop_button")
    .addEventListener("click", function (e) {
      initRythm();
    });
}
function mic() {
  document
    .getElementById("mic_start_button")
    .addEventListener("click", function (e) {
      if (isStart) {
        return;
      }
      initRythm();
      addRythmClass(this);
      rythm.plugMicrophone();
      isStart = true;
      rythm.start();
    });

  document
    .getElementById("mic_stop_button")
    .addEventListener("click", function (e) {
      initRythm();
    });
}

function initRythm() {
  Array.from(document.getElementsByClassName("rythm")).forEach((element) => {
    element.classList.remove("music_dance");
  });
  rythm.stop();
  rythm.setMusic("");
  isStart = false;
}

function addRythmClass(e) {
  e.closest(".rythm_area")
    .getElementsByClassName("rythm")[0]
    .classList.add("music_dance");
}
```



# さいごに

やり方が違ったり、もっといいやり方、認識が間違っているよというようなことをお気づきの方は、はコメントしていただけると幸いです。

最後まで読んでいただきありがとうございました。


# 参考文献

https://okazari.github.io/Rythm.js/