jsで簡単なオーディオプレーヤーを作る

<h2>機能</h2>
`Javascript`と`jQuery`ライブラリで以下の機能を搭載するオーディオプレーヤーを作った。
・ボタンを押すことで音楽の再生/一時停止、停止
・スライダーを動かしてボリュームの調整
・再生と同時に再生中の楽曲の名称とアーティスト名、再生時間を表示

ファイルの構造としては、`media1/templates`下に`music.html`を配置し、mp3ファイルを`media1/music`下に配置。
まず、`HTML`は以下の通り

```HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>おーでぃお</title>
    <link rel='stylesheet' href='../static/style.css'>
　　<!-- jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!-- jQuery UI -->
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
  </head>

  <body>
    <!--再生時間表示部分-->
    <div class="timeviewr" id='timeviewr'>00:00:00</div><br><br>
    <!-- コントローラー部分 -->
    <form class='audioform'>
　　　<!--曲名を表示する部分は、空白を入れておく-->
      <div id="playing_title" class='playing_title'></div><br>
      <!-- ボタン -->
      <div class="btns">
        <button style='font-size: 15px;' type="button" id="play_btn" class='play_btn'>Play</button>
        <button type="button" id='stop_btn' class="stop_btn" style='font-size: 15px;'>Stop</button>
      </div>
      <img src='../static/volumesmall.png' class="icon-volume-down">
      <div class="volume" id='volume'></div><br> <!--スライダー設置部分-->
      <img src='../static/volumebig.png' class="icon-volume-up">
    </form><br><br>

    mp3ファイルは
    <ul>
      <li><a href='https://the-arcadium.net/'>https://the-arcadium.net/</a></li>
      <li><a href="https://amachamusic.chagasi.com/genre_darktechno.html">甘茶の音楽工房</a></li>
    </ul>
    から拝借しました。
　　<!--最後にjsファイルを読み込む-->
    <script type="text/javascript" src='music.js'></script>
  </body>

</html>
```
```css:static.css

/* music.html */
.timeviewr{
  position: relative;
  left: 50px;
  top: 80px;
  font-size: 30px;
}

/* コントローラ部分*/
.audioform{
  border: 3px solid cadetblue;
  background-color: darkslategray;
  border-radius: 5px;
  height: 125px;
  width: 270px;
  position: relative;
  top: 30px;
  left: 30px;
}

.playing_title{
  background-color: black;
  height: 55px;
}

button.play_btn, button.pause_btn, button.stop_btn{
  position: relative;
  bottom: 15px;
  left: 37px;
  height: 30px;
  width: 60px;
  border-radius: 5px;
}

.next_btn{
  width: 30px;
  position: relative;
  bottom: 15px;
  left: 40px;
}

.icon_play{
  width: 25px;
}

.icon-volume-down{
  width: 16px;
  position: relative;
  bottom: 7px;
  left: 10px;
}

.icon-volume-up{
  position: absolute;
  width: 27px;
  left: 233px;
  bottom: 2px;
}

/* スライダー */
.volume{
  position: relative;
  bottom: 30px;
  left: 32px;
  width: 195px;
}

/* 押した後のボタンの色 */
button.pushed_play, button.pushed_pause, button.pushed_stop{
  background-color: darkgrey;
}
```
![Screenshot_2020-01-04 ワイのホームページ(6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/b22f0aa8-f4ad-ab2d-827c-08d715e4d08d.png)
※画像中の[https://the-arcadium.net/](https://the-arcadium.net/)は現在アクセスできないです。
実はこれらの機能をデフォルトで持つコントローラのコードがあり、`<audio src='../static/TheFatRat+-+Unity.mp3' controls></audio>`を記述すると、
![Screenshot_2020-01-04 ワイのホームページ(5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/493d34dd-93a4-bb1e-6f51-f121e47ae118.png)
このようなコントローラが出現する。ここではあえて使わないで、オリジナルのオーディオを作成する。
次に`JavaScript`ファイルを編集

```javascript:music.js
// 音楽ファイルを連想配列に格納
var filelist = [
  {name: "Unity", artist: "TheFatRat", url:'TheFatRat+-+Unity.mp3'},
  {name: "MidNightMoon", artist: "甘茶の音楽工房", url: 'midnightmoon.mp3'},
];
const dir = '../music/' // ../musicをいちいち記述するのが面倒なので別に分ける

var now_file = filelist[0]; // 曲を選択
// new演算子によりインスタンス化して、Audioクラスをオブジェクト化
var Music = new Audio(dir + now_file.url);
var playFlag = false; // 再生中か否かを表すフラグを定義
var playbtn = document.getElementById('play_btn');
var stopbtn = document.getElementById('stop_btn');
var crtTime = document.getElementById('timeviewr'); // 再生時間表示部分取得

// 曲を停止したときオーディオをリセットする
var ClearPlayer = function(){
  playFlag = false;
  print(playing_title, "Stopped");
  crtTime.innerHTML = "00:00:00"
};
// 曲の状態とタイトル、作者を表示する
// stateはnow_playing, Stopped, Pausedの3種類
function print(element, state){
  element.innerHTML = state + ": " + now_file.name + '  ' + now_file.artist;
  element.innerHTML = element.innerHTML.fontcolor('white');
  element.innerHTML = element.innerHTML.fontsize('4px');
};
// 再生/一時停止機能
// addEventListenerを使用することで処理の上書きを可能にした
$(function Play(){
  // playボタンをクリックした時
  playbtn.addEventListener('click', function(){
    if (playFlag==false){ // 再生されていないとき
      // 時間のカウント
      Music.addEventListener('timeupdate', function(){
        var sec = '0' + Math.floor(Music.currentTime % 60); // 秒数
        var min = '0' + Math.floor(Music.currentTime / 60); // 分数
        sec = sec.substr(sec.length-2, 2);
        min = min.substr(min.length-2, 2);
        var totalSec ='0' + Math.floor(Music.duration % 60); //秒数
        var totalMin ='0' + Math.floor(Music.duration / 60); //分数
        totalSec = totalSec.substr(totalSec.length-2, 2);
        totalMin = totalMin.substr(totalMin.length-2, 2);
        crtTime.innerHTML = min + ":" + sec + ' [' +  totalMin + ':' + totalSec + ']';
      }, true);
      playFlag = true; // 再生中フラグを立てる
      Music.play(); // 音楽を再生
      play_btn.innerHTML = "Pause" // ボタンをplay→pauseに変化
      play_btn.innerHTML = play_btn.innerHTML.fontsize('4px')
      print(playing_title, "now playing") // 再生中タイトルの表示
      // ボタンが押されたとき、色を付け、他のボタンの色を消す
      $('#pause_btn').removeClass('pushed_pause'); 
      $('#stop_btn').removeClass('pushed_stop');
      $(this).addClass('pushed_play');
    }
    else{ // 再生されているとき、ボタンを押すと一時停止
      playFlag = false;
      play_btn.innerHTML = "Play"; // ボタンを押すとPause→Playに文字を変化
      print(playing_title, "Paused")
      $('#stop_btn').removeClass('pushed_stop');
      Music.pause();
    }
  }, false);
  // 一時停止中の停止ボタン押下イベント
  if (play_btn.innerHTML == "Play"){
    stopbtn.addEventListener('click', Stop());
  }
});

// 曲の再生が終わった時、最初の状態に戻す
$(function end(){
  Music.addEventListener('ended', function(){
    print(playing_title, "Finished")
    $('#play_btn').removeClass('pushed_play');
    $('#stop_btn').removeClass('pushed_stop');
    play_btn.innerHTML = "Play";
  });
});

// 停止ボタン
function Stop(){
  // ボタンを押している間だけボタンを色付けする
  stopbtn.addEventListener('mousedown', function(){
    $(this).addClass('pushed_stop');
  });
  // ボタンを離したとき戻す
  stopbtn.addEventListener('mouseup', function(){
    $(this).removeClass('pushed_stop');
  });
  $('#stop_btn').on('click', function(){
    $('#play_btn').removeClass('pushed_play');
    play_btn.innerHTML = "Play"
    Music.pause();
    Music.currentTime = 0; // 経過時間を0にして完全停止
    ClearPlayer();
  });
};

// ボリューム調整のスライダー
$(function Slider(){
  $('#volume').slider({
    min: 0,
    max: 100,
    value: 50, //デフォルト値
    range: 'min', // min方向に色を付ける
    change: function(){
      var value = $('#volume').slider('value'); // デフォルト値を受け取る
      Music.volume = (value/100); // 受け取った値を100で割る
    }
  });
});

```
<h2>クリックイベント</h2>
クリックイベントには3つあり、
・`onclick`属性（HTMLの`input`タグに直接`onclick`属性を記述し、`function`を指定）
・`onclick`プロパティ（`element.onclick=function`の記述）
・`addEventListener()`
を使う方法だ。[こちら](https://qiita.com/KKKarin/items/ccb8ed361ab9acd1f9cf)に書いてあるように、`onclick`属性、`onclick`プロパティでは処理の上書きができず、複数のイベントを追加できない。よって、`addEventListener()`を使う方が汎用性が高い。ちなみに`addEventListener()`でスライダー(音量調整のバー)も作成できるのだが、どうやらfirefoxではうまく機能しないので、`jQuery`でスライダーを作成した。chromeやsafariでは機能しているらしい（[参考サイト](https://yoheim.hatenadiary.org/entries/2011/07/10)）。

<h2>innerHTML</h2>
`innerHTML`はHTML要素の中身を動的に取得・変更できるメソッド。ただし中身を変更する場合、変更した後の要素は既存の要素ではなく、新たなHTML要素として置き換えられる。HTML要素を挿入する`insertAdjacentHTML()`の方が処理は速いらしい。詳しくは[こちら](https://qiita.com/amamamaou/items/624c22adec32515e863b)。

<h2>時間のカウント処理</h2>
時間のカウント処理は[こちら](https://ascii.jp/elem/000/000/525/525808/index-6.html)をまるごと利用させてもらった。現在の再生時間を取得するには、`currentTime`を使用する。

<h2>ボタンの色付け処理</h2>
ボタンが押されたときの色付け処理については、それぞれのボタンに押されたときのクラスを別に用意し、色を付けるときには`addClass()`でクラスを追加し、色を消したいときには`removeClass()`でクラスを削除する、といった仕組みで変化させた。ちなみに`toggleClass()`はクリックするたびに追加したり削除したりする。詳しくは[こちら](https://php-archive.net/html/change-style-clicked-button/)のサイトへ。

<h2>CSSでの複数クラスの指定での注意</h2>
複数の要素やクラスに対して同時に指定するときはカンマをつける。

```css
.class1, .class2{
  /**処理**/
}
```
同じ要素内にクラス名を複数指定している場合と、入れ子構造の場合とで指定方法が違うので注意されたい。[参考サイト](http://ooigawa-bitter-sweet.hatenablog.com/entry/2013/07/10/233000_1)

初心者である自分が少し悩んだエラーには、

```
document.getElementById("…");  null
```
があったが、これは`HTML`要素よりも先に`javascript`ファイルが読み込まれていることで、`HTML`要素を読み込む前に`javascript`が`HTML`要素を参照して値がみつからない、ということだった。よって、`<body>`の最後に`<script>`ファイルを置いて最後に`javascript`を読み込ませることで解決した。[こちら](http://vatscy.github.io/blog/2014/02/22/document-ready/)に例を交えて解説されている。

再生すると、
![Screenshot_2020-01-06 ワイのホームページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/344f9bda-346e-4c0b-66e4-16b6e6f8ff68.png)

他参考サイト
[HTML5 Audio Playerを改良しました: ボリューム機能追加、再生ボタン機能拡張など](https://mae.chab.in/archives/2307)
[audioタグvideoタグでのリスト再生](https://www.systemexpress.co.jp/htmlcss/audiovideoplayer.html)
[HTML5のaudio要素、メソッドとイベント](http://k-hiura.cocolog-nifty.com/blog/2011/11/html5audio-72e6.html)
BGM・効果音のフリー素材　[OtoLogic](https://otologic.jp/)
アイコンのフリー素材　[ICOOON MONO](https://icooon-mono.com/?s=%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0)
フリー素材BGM　[TheFatRat](https://app.box.com/s/2tt7sdwsu0wbngoqroog/folder/346885813)　[甘茶の音楽工房](https://amachamusic.chagasi.com/genre_darktechno.html)