Kawałek Kodu

Jeśli słoń nie nadepnął Ci na ucho, to pewnie wiesz kiedy grają, a kiedy nie. I bardzo dobrze, bo dzisiejszy wpis nie wymaga znajomości w jakiej notacji zagrana została melodia. Pokażę Ci jak obsługiwać audio na stronie www. Będziesz mógł również doświadczyć na własnych uszach jak to działa przy standardowym użyciu i niestandardowym użyciu.

Preludium.

Wraz z pojawieniem się HTML5 przywędrował z nim tag AUDIO i powiązany obiekt Audio umożliwiający dostep do metod i właściwości tego elementu. Możemy ustawić źródło lub źródła dźwięku, tak jak źródła dla obrazka czy wideo. Jesteśmy w stanie odwtarzać, zatrzymywać i przewijać ścieżkę. Mamy też informację zwrotną w jakim momencie odtwarzania jest muzyka jaki i postępy odtwarzania wywoływane przez zdarzenie onupdatetime.

Interludium.

Wykorzystamy dziś cechy tego obiektu i zbudujemy prosty player z playlistą.
Będziemy potrzebować:

  • przycisku play/pause i tu wykorzystamy metody play() oraz pause()
  • paska postępu z możliwością wizualizacji progressu i przewijania utworu (wykorzystamy właściwości duration oraz currentTime),
  • playlisty z możliwością wyboru utworu do odegrania i autostartu (wykorzystamy właściwość src).

Zacznijmy od kodu HTML:

<div id="player">
  <button></button>
  <div class="progress" tabindex="0"><span></span></div>
  <ul class="playlist">
    <li tabindex="1" data-src="brobob.mp3">Gitarowe brzdąkanie</li>
    <li tabindex="2" data-src="crowd-cheering.mp3">Oklaski</li>
    <li tabindex="3" data-src="wave.mp3">Szum fali</li>
  </ul>
</div>

BUTTON posłuży nam za przycisk play/pause, DIV z klasą progress użyjemy do paska postępu. Nie używamy elementu PROGRESS, bo ten i tak nie ma obsługi zdarzenia change, które chcielibyśmy użyć w momencie przewijania paska przez użytkownika. No i element UL, który będzie listą utworów. Element dodatkowo mają ustawiony atrybut tabindex, dzięki któremy będą otrzymywać focus na wciśnięcie tabulatora i będziemy mogli obsłużyć je klawiaturą, po oprogramowniu.

CSS:

#player button {
  border: 0;
  background: transparent;
}

#player button:after {
  content: '\23F8'; /* ikona pause */
}

#player button.playing:after {
  content: '\25B6'; /* ikona play */
}

/* kontener na pasek postępu */
#player div.progress {
  width: 200px;
  height: 15px;
  position: relative;
  border: 1px solid #000;
  text-align: center;
}

/* wskaźnik postępu */
#player div.progress span {
  display: block;
  width: 0;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  background: #f00;
}

/* pokażemy też aktualny czas */
#player div.progress:after{
  content: attr(data-time);
}

/* elementy playlisty */
#player .playlist li{
  float: left;
  clear: left;
}

Stylujemy tylko podstawę. Player możesz upiększyć w dowolny sposób.

No i to, na co wszyscy czekają:

/* obiekt audio */
var audio = new Audio();
/* status odgrywania */
var playing = false;

/* przy kliknięciu elementu playlisty (utworu)
   ustawiamy nowe źródło Audio i startujemy,
   progress ustawiamy na 0%
*/
document.querySelector('#player .playlist').addEventListener('click', function(e) {
  if (e.target.tagName === 'LI') {
    document.querySelector('#player .progress span').style.width = 0;
    audio.src = e.target.dataset.src;
    audio.play();
    playing = true;
    document.querySelector('#player button').classList.add('playing');
  }
});

/* spacja lub enter na elemencie playlisty
   uruchamia utwór
*/
document.querySelector('#player .playlist').addEventListener('keydown', function(e) {
  if (e.target.tagName === 'LI' && (e.keyCode === 32 || e.keyCode === 13)) {
    document.querySelector('#player .progress span').style.width = 0;
    audio.src = e.target.dataset.src;
    audio.play();
    playing = true;
    document.querySelector('#player button').classList.add('playing');
  }
});

/* podpinamy się pod zdarzenie ontimeupdate
   i aktualizujemy pasek postępu
*/
audio.addEventListener('timeupdate', function() {
/* długość ścieżki */
  var length = audio.duration;
/* aktualny postęp */
  var currentTime = audio.currentTime;

/* jeśli utwór się skończył,
   czyścimy src
   to ustawiamy progress na 0%,
   zmieniamy status playing,
   ustawiamy ikonę dla przycisku
*/
  if(currentTime === length){
    audio.removeAttribute('src');
    document.querySelector('#player .progress').setAttribute('data-time', '');
    document.querySelector('#player .progress span').style.width = 0;
    playing = false;
    document.querySelector('#player button').classList.remove('playing');
  }
/* jeśli trwa odwtarzanie,
   to ustawiamy progress
   na podstawie aktualnego postępu
   i długości całego utworu
   oraz atrybut data-time
   dzięki czemu w pasku widać
   aktualny czas
*/
  else{
    document.querySelector('#player .progress').setAttribute('data-time', currentTime);
    document.querySelector('#player .progress span').style.width = (currentTime / length) * 100 + '%';
  }
});

/* dodajemy obsługę przycisku
   play/pause
*/
document.querySelector('#player button').addEventListener('click', function(e) {
  e.preventDefault();
/* jeśli załadowany jest jakiś utwór */
  if(audio.src){
      if (playing) {
        audio.pause();
        this.classList.remove('playing');
      } else {
        audio.play();
        this.classList.add('playing');
      }
      playing = !playing;
  }
});

/* dodajemy obsługę kliknięcia
   na pasku postępu
   właściwość currentTime jest
   read/write
*/
document.querySelector('#player .progress').addEventListener('click', function(e) {
  e.preventDefault();
  var length = audio.duration;
  var progressWidth = this.offsetWidth;
/* znając długość całego utworu
   i miejsce kliknięcia na pasku
   możemy na podstawie proporcji
   ustawić odpowiedni moment
   ścieżki muzycznej
*/
  audio.currentTime = e.offsetX / this.offsetWidth * length;
});

/* do paska postępu dodajemy
   obsługę przewijania +-1s
   dzięki strzałkom lewo/prawo
*/ 
document.querySelector('#player .progress').addEventListener('keydown', function(e) {
  if (e.keyCode === 37) {
    audio.currentTime--;
  } else if (e.keyCode === 39) {
    audio.currentTime++;
  }
});

I w działaniu:

Postludium.

W przykładzie utworzyliśmy jeden obiekt Audio ponieważ w danym momencie odtwarzany jest maksymalnie jeden utwór. Jeśli zaistnieje potrzeba odtwarzania kilku dźwięków jednocześnie, to dla każdego trzeba utworzyć odrębny obiekt Audio.

Dla relaksu polecam wypróbowanie użycia obiektu Audio w dosyć niekonwecjonalny sposób. W wolnej chwili możesz zagrać na... domofonie! Ten znajdziesz pod adresem: http://domofonika.pl

 

Przydatne linki:
Właściwości i metody obiektu Audio

Próbki dźwięków pochodzą z:
http://www.largesound.com/ashborytour/sound/
https://www.sample-videos.com/download-sample-audio.php