コード
’1.mp3’, ’2.mp3’, ’3.mp3’という音声ファイルを再生したいとする
<script> const audioElements = {}; function btn(filePath, button) { if (!audioElements[filePath]) { // 新しい音声ファイルを再生 audioElements[filePath] = new Audio(filePath); audioElements[filePath].play(); button.classList.add('playing'); // ボタンのスタイルを変更 // 音声再生終了時のイベントハンドラを設定 audioElements[filePath].addEventListener('ended', function() { button.classList.remove('playing'); // ボタンのスタイルを元に戻す delete audioElements[filePath]; // オブジェクトから削除 });} else { // 既存の音声ファイルを停止 audioElements[filePath].pause(); audioElements[filePath].currentTime = 0; // 音声を最初から再生できるようにリセット delete audioElements[filePath]; // オブジェクトから削除 button.classList.remove('playing'); // ボタンのスタイルを元に戻す }} </script> <style> button{ background-color: #47848b; color: white; border-radius: 1em;border-width: 0; &:hover { background-color: #4d9fa9; } &.playing { background-color: #14656e; /* 再生中のボタンの背景色を変更 */ } } </style> <button onclick="btn('1.mp3', this)">ボタン1</button> <button onclick="btn('2.mp3', this)">ボタン2</button> <button onclick="btn('3.mp3', this)">ボタン3</button>
機能
- ひとつの関数で複数ファイルの音声の再生状態が管理できるので、html側で
<button onclick="btn('4.mp3', this)">ボタン1</button>
などとパスだけを異なるbuttonタグを足すだけで異なるボタンを増やせる。ネット上の他の実装のようにclass名を書いてjs側でaddEeventListener()をボタン毎に書く必要がなく、一つの関数を多数の音声ファイルに使いまわせ、html側で音声ファイルパスを指定できる。
- マウスホバーで色が変化する。
- 再生中は色が変わる。
- 再生中にボタンを押すと再生が止まる。
背景
私のサイトでは何年か前から「さなボタン」に触発されて、「ミクボタン」という、押すと初音ミクの声が聴けるだけのボタンを設置しているが、ホームページをマークダウン化するにあたって、マークダウン中のhtmlでの入力量が最小になるように書き換えたかった。chatGPTに5回程度書き直させるとほとんど完璧な回答が出てきて、ネット上の実装よりもずっといいように思えたので公開した。