ReactのOnClick時に音が鳴るようにした時の記録


経緯

Reactの練習として簡単な貯金箱アプリを作成しました。
イメージとしてはこのような感じ↓

作成している途中に、「これ+と-ボタンをクリックした時に"チャリン♪"って音鳴らしたいなー」と思ったので実装方法と、その際に困ったことを記録として残しておきます!

実際のコード

実際のボタン部分とオーディオを作成するためのコードは以下の通りです。(該当部分のみ載せています)

ボタン部分↓

<button className="btn" onClick={() => {
  audioPlay(true);
  setCount(count + 1);
  props.setSum(props.unit + props.sum);
}}></button>

<button className="btn" onClick={() => {
 audioPlay(false);
setCount(count - 1);
props.setSum(-props.unit + props.sum);
}}></button>

↓オーディオ作成、再生部分

  const checkUnit = (isIncrement: boolean) => {
    if (isIncrement) {
      if (props.unit < 1000) {
        return "../audio/inCoin.mp3"
      } else {
        return "../audio/inBill.mp3"
      }
    } else {
      if (props.unit < 1000) {
        return "../audio/outCoin.mp3"
      } else {
        return "../audio/outBill.mp3"
      }
    }
  }

  const audioPlay = (is_increment: boolean) => {
    const audio = new Audio(checkUnit(is_increment))
    audio.play().then(() => {
      console.log("Audio started!")
    })
      .catch(error => console.warn(error))
  }

内容としてはボタンをクリックすると、カウント数と、親コンポーネントで管理している合計金額が変化するというとてもシンプルな内容になっています。

オーディオ作成・再生部分では、audioPlay関数内の

const audio = new Audio(checkUnit(is_increment))

の部分でオーディオ要素を作成しており、引数として音源のURLを指定する必要があるのですが、今回お札と小銭、+と-でそれぞれ使用する音源を分けたかったので、checkUnit関数で場合分けを行いました。

  const checkUnit = (isIncrement: boolean) => {
    if (isIncrement) {
      if (props.unit < 1000) {
        return "../audio/inCoin.mp3"
      } else {
        return "../audio/inBill.mp3"
      }
    } else {
      if (props.unit < 1000) {
        return "../audio/outCoin.mp3"
      } else {
        return "../audio/outBill.mp3"
      }
    }
  }

お札と小銭で音源を変えることはさほど難しくはなかったのですが、プラスとマイナスはどのように分けようか...と考えて、今回はis_incrementをtrue/falseで渡すことでプラスをクリックしているかマイナスをクリックしているかを分けるようにしました。

よしできた!と思い、ボタンをクリックしてみたのですが、クリックしてもなかなか音源が再生されず・・・。
調べてみたところ、new Audioの引数に指定するURLはindex.htmlからのパスを指定する必要があるみたいです。

index.htmlからのパスにすることと、条件分岐をすることで4つのパターンの音源を使い分けて実装を行うことができました!

以上、私が実際に実装をする上で困ったことでした!!

最後に

今回の内容としてはすごく基礎的な部分だと思います。
少しずつですが、実装を通して自分のできることを増やしていければと思います