Research - Patrycja20/VirtualPiano GitHub Wiki

Przykład:

Mały pomysł na to, jak odgrywać dźwięki

Odgrywanie dźwięków przez znacznik audio ma poważną wadę - opóźnienie. Po kliknięciu na przycisk start (albo na klawisz, gdy podepniemy onMouseDown, itp) dźwięk jest odgrywany po pewnej malutkiej przerwie. Pianino ma to do siebie, że musi być "responsywne" - naciskasz i gra, od razu, bez nawet najmniejszej przerwy. Na szczęście jest na to sposób!. Mianowicie - musimy użyć JavaScriptowego obiektu Audio. Po załadowaniu do niego dźwięku, odgrywany jest natychmiastowo. A więc poniżej wszystko to, co wymyśliłem.

Przycisk pianina pozostaje bez zmian. Możemy wywalić z niego nawet znacznik <audio></audio>

       <li id="f3" className="white" onMouseDown={(e) => this.play(e)} onMouseUp={(e) => this.stop(e)}>
          <audio></audio>
        </li>

Jak widać, dodane zostały eventy onMouseDown oraz onMouseUp. Dlaczego nie onClick? Ano dlatego, że dźwięk musi być grany tak długo, jak jest wciśnięty klawisz myszki (onMouseDown). Na razie zrobione tylko pod myszkę, jak wszystko zadziała, to dorobimy tak, by działało pod naciśnięcie klawisza na klawiaturze.

Powstaje zasadnicze pytanie - jak mogą wyglądać funkcje this.play() oraz this.stop()? Już pokazuję.

// ścieżka do plików, jeżeli chcemy zmieniać w przyszłości 
// dźwięki, to można ją przekazywać z propsów
const PIANO_SOUNDS = 'sounds/piano_mp3/';

class Keyboard extends React.Component {

  playingSounds = []; // tablica z aktualnie granymi dźwiękami 
 //(by móc złapać takowy i go zatrzymać po puszczeniu klawisza)

  // funkcja play
  play = (event) => {
    const soundName = event.target.id; // pobiera z ID klawisza nazwę dźwięku
    const audio = new Audio(`${PIANO_SOUNDS}${soundName}.mp3`); // tworzy string 
                                        //np. "sounds/piano_mp3/a4.mp3"
    audio.play(); // zaczyna go odgrywać
    this.playingSounds[soundName] = audio; // wrzuca obiekt audio tego dźwięku 
    // do tablicy pod indeks 'soundName' czyli po naciśnięciu na klawisz 
    // z dźwiękiem "a4", zostanie stworzony obiekt 
    // Audio("sounds/piano_mp3/a4.mp3"), a następnie zostanie ten obiekt 
    // przypisany do tablicy pod indeksem "a4".
  };

  stop = (event) => {
    // pobieramy nazwę klawisza, jak wyżej, w funkcji play
    const soundName = event.target.id; 

    const audio = this.playingSounds[soundName] || null; // pobieramy grający dźwięk. 
                           // Jeżeli nie ma takowego, to wpisujemy null
    if (audio === null) return; // jeśli nie znaleźliśmy grającego dźwięku, 
                           // to kończymy funkcję i nic nie robimy

    // jeśli znaleźliśmy taki dźwięk, to można go wyciszyć. 
    // Służy do tego metoda `pause()`, która wstrzymuje granie
    // oraz właściwość `currentTime`, która resetuje wskaźnik w
    //  odtwarzaczu na początek dźwięku (by następnym razem
    // zagrać od początku.
    setTimeout(() => {
      audio.pause();
      audio.currentTime = 0;
    }, 500);
    // po co tutaj funkcja `setTimeout`? To takie oszukaństwo,
    //  by dźwięk pograł sobie jeszcze pół sekundy, by nie kończył
    //  się od razu po puszczeniu klawisza.
    // takie szaleństwo jak w chińskich zabaweczkach na odpuście :D
  };

// funkcja render() i dalej cały komponent Keyboard
// ...
// ...
}

Powstaje jedno pytanie - czy chcemy zatrzymywać dźwięk po puszczeniu klawisza? Na wielu piano-online tak się nie dzieje, dźwięk jest grany do tego czasu, aż sam nie wybrzmi.

⚠️ **GitHub.com Fallback** ⚠️