Das Web braucht mehr (geschmackvolle) Sounds!
Diese Bibliothek funktioniert nur mit React DOM, aber @remigallego hat eine Alternative für React Native erstellt! Schauen Sie sich React-Native-Use-Sound an.
Dieses Projekt ist „semi-maintained“?
Ich habe derzeit nicht die nötige Bandbreite, um Randprobleme zu untersuchen oder bei der Fehlerbehebung zu helfen, aber ich habe vor, es mit den wichtigsten React-Releases auf dem neuesten Stand zu halten und sowohl schwerwiegende als auch häufige Probleme zu beheben.
Wenn Sie Ideen für Funktionen haben oder auf seltsame Macken stoßen, empfehle ich dringend, das Projekt abzuspalten und es zu Ihrem eigenen zu machen! Es mag einschüchternd wirken, aber die Quelle ist nicht so komplex wie bei vielen anderen NPM-Paketen; Ich überlasse die gesamte harte Audioarbeit Howler. Wenn Sie React schon länger verwenden und mit Hooks vertraut sind, sollten Sie sich mit dem Code dieses Pakets wie zu Hause fühlen.
Das Paket kann mit Garn hinzugefügt werden:
yarn add use-sound
Oder verwenden Sie NPM:
npm install use-sound
UMD-Build verfügbar auf unpkg.
Wenn Ihr Projekt TypeScript verwendet, sollten Sie auch das Paket @types/howler
als Entwicklungsabhängigkeit installieren.
Das Tutorial enthält viele Demos sowie Anweisungen zum Finden und Vorbereiten von Soundeffekten. Es ist ein großartiger Ausgangspunkt.
Sie können sich auch das Bilderbuch ansehen , das viele schnelle Beispiele enthält.
import useSound from 'use-sound' ;
import boopSfx from '../../sounds/boop.mp3' ;
const BoopButton = ( ) => {
const [ play ] = useSound ( boopSfx ) ;
return < button onClick = { play } > Boop! < / button > ;
} ;
Diese Demo spielt den Ton nur ab, wenn Sie mit der Maus über ein Element fahren. Der Ton pausiert, wenn die Maus das Element verlässt:
HINWEIS: Viele Browser deaktivieren Töne, bis der Benutzer irgendwo auf die Seite geklickt hat. Wenn Sie in diesem Beispiel nichts hören, klicken Sie auf eine beliebige Stelle und versuchen Sie es erneut.
import useSound from 'use-sound' ;
import fanfareSfx from '../../sounds/fanfare.mp3' ;
const FanfareButton = ( ) => {
const [ play , { stop } ] = useSound ( fanfareSfx ) ;
return (
< button onMouseEnter = { ( ) => play ( ) } onMouseLeave = { ( ) => stop ( ) } >
< span role = "img" aria-label = "trumpet" >
?
< / span >
< / button >
) ;
} ;
Mit der Option playbackRate
können Sie die Geschwindigkeit/Tonhöhe des Samples ändern. Dieses Beispiel spielt einen Sound ab und macht ihn jedes Mal um 10 % schneller:
import useSound from 'use-sound' ;
import glugSfx from '../../sounds/glug.mp3' ;
export const RisingPitch = ( ) => {
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( glugSfx , {
playbackRate ,
// `interrupt` ensures that if the sound starts again before it's
// ended, it will truncate it. Otherwise, the sound can overlap.
interrupt : true ,
} ) ;
const handleClick = ( ) => {
setPlaybackRate ( playbackRate + 0.1 ) ;
play ( ) ;
} ;
return (
< Button onClick = { handleClick } >
< span role = "img" aria-label = "Person with lines near mouth" >
?
< / span >
< / Button >
) ;
} ;
useSound
erfordert einen Pfad zu einer Audiodatei und es ist nicht offensichtlich, wie man einen in einer React-Anwendung bereitstellt.
Mit create-react-app
können Sie eine MP3-Datei „importieren“. Es wird in einen dynamisch generierten Pfad aufgelöst:
import someAudioFile from '../sounds/sound.mp3' ;
console . log ( someAudioFile ) ; // “/build/sounds/sound-abc123.mp3”
Wenn Sie versuchen, diesen Trick in einem anderen React-Build-System wie Next.js anzuwenden, erhalten Sie möglicherweise eine Fehlermeldung wie diese:
Möglicherweise benötigen Sie einen geeigneten Loader, um diesen Dateityp zu verarbeiten. Derzeit sind keine Loader für die Verarbeitung dieser Datei konfiguriert.
Das Problem besteht darin, dass Webpack (der Bundler, der unter der Haube zum Generieren von JS-Bundles verwendet wird) nicht weiß, wie eine MP3-Datei verarbeitet wird.
Wenn Sie Zugriff auf die Webpack-Konfiguration haben, können Sie sie aktualisieren, um den File-Loader zu verwenden, der einen dynamischen, öffentlich zugänglichen Pfad zur Datei erstellt.
Alternativ stellen Ihnen die meisten Tools einen „öffentlichen“ (create-react-app, Next.js) oder einen „statischen“ (Gatsby) Ordner zur Verfügung. Sie können Ihre Audiodateien dort ablegen und dann einen Zeichenfolgenpfad verwenden.
Die Sounddateien, die Sie mit use-sound
verwenden, folgen denselben Regeln wie andere statische Assets wie Bilder oder Schriftarten. Befolgen Sie die Anleitungen für das Meta-Framework Ihrer Wahl:
️ Asynchrone Klangpfade?️ Wenn die URL zu Ihrer Audiodatei asynchron geladen wird, können Probleme auftreten. Dies ist wahrscheinlich nicht das richtige Paket für diesen Anwendungsfall.
Im Interesse des Benutzers erlauben Browser Websites erst dann Ton zu erzeugen, wenn der Benutzer mit ihnen interagiert hat (z. B. indem er auf etwas geklickt hat). Es wird kein Ton erzeugt, bis der Benutzer auf etwas klickt, tippt oder etwas auslöst.
useSound
macht sich dies zunutze: Da wir wissen, dass Sounds beim Laden nicht sofort benötigt werden, können wir eine Drittanbieter-Abhängigkeit verzögert laden.
useSound
fügt Ihrem Bundle etwa 1 KB gzip hinzu und ruft nach dem Laden asynchron ein zusätzliches Paket ab, das etwa 9 KB gzip umfasst.
Wenn der Benutzer tatsächlich auf etwas klickt, das Geräusche macht, bevor diese Abhängigkeit geladen und abgerufen wurde, ist dies ein No-Op (alles funktioniert weiterhin, aber es wird kein Soundeffekt abgespielt). Meiner Erfahrung nach kommt das äußerst selten vor.
Betrachten Sie den folgenden Codeausschnitt:
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
dient nicht nur als Anfangswert für den Soundeffekt. Wenn sich playbackRate
ändert, beginnt die Wiedergabe des Tons sofort mit einer neuen Geschwindigkeit. Dies gilt für alle Optionen, die an den useSound
Hook übergeben werden.
Der useSound
Hook benötigt zwei Argumente:
HookOptions
)Es erzeugt ein Array mit zwei Werten:
ExposedData
) Wenn Sie die Funktion zum Abspielen des Sounds aufrufen, können Sie ihr eine Reihe von Optionen ( PlayOptions
) übergeben.
Lassen Sie uns diese nacheinander durchgehen.
Beim Aufruf von useSound
können Sie verschiedene Optionen übergeben:
Name | Wert |
---|---|
Volumen | Nummer |
Wiedergaberate | Nummer |
unterbrechen | Boolescher Wert |
soundEnabled | Boolescher Wert |
Sprite | SpriteMap |
[delegiert] | — |
volume
ist eine Zahl von 0
bis 1
, wobei 1
die volle Lautstärke und 0
die vollständige Stummschaltung bedeutet.playbackRate
ist eine Zahl zwischen 0.5
und 4
. Es kann verwendet werden, um die Probe zu verlangsamen oder zu beschleunigen. Wie bei einem Plattenspieler wirken sich Geschwindigkeitsänderungen auch auf die Tonhöhe aus.interrupt
gibt an, ob sich der Ton „überlappen“ darf, wenn die play
-Funktion erneut aufgerufen wird, bevor der Ton zu Ende ist.soundEnabled
können Sie einen Wert übergeben (normalerweise aus dem Kontext oder Redux oder etwas Ähnlichem), um alle Sounds stummzuschalten. Beachten Sie, dass dies in den PlayOptions
überschrieben werden kann, siehe untensprite
können Sie einen einzigen useSound
Hook für mehrere Soundeffekte verwenden. Siehe „Sprites“ unten. [delegated]
bezieht sich auf die Tatsache, dass jedes zusätzliche Argument, das Sie in HookOptions
übergeben, an den Howl
Konstruktor weitergeleitet wird. Weitere Informationen finden Sie weiter unten unter „Notluken“.
play
Wenn Sie den Hook aufrufen, erhalten Sie als erstes Element im Tupel eine Play-Funktion zurück:
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Sie können diese Funktion ohne Argumente aufrufen, wenn Sie den Ton auslösen möchten. Sie können es auch mit einem PlayOptions
-Objekt aufrufen:
Name | Wert |
---|---|
Ausweis | Zeichenfolge |
forceSoundEnabled | Boolescher Wert |
Wiedergaberate | Nummer |
id
wird zur Sprite-Identifizierung verwendet. Siehe „Sprites“ unten.forceSoundEnabled
können Sie den booleschen Wert soundEnabled
überschreiben, der an HookOptions
übergeben wird. Im Allgemeinen möchten Sie dies niemals tun. Die einzige Ausnahme, die ich gefunden habe: das Auslösen eines Tons auf die Schaltfläche „Stumm“.playbackRate
ist eine weitere Möglichkeit, eine neue Wiedergaberate festzulegen, genau wie in HookOptions
. Im Allgemeinen sollten Sie es vorziehen, dies über HookOptions
zu tun, da dies ein Notausstieg ist. Der Hook erzeugt ein Tupel mit 2 Optionen, der Play-Funktion und einem ExposedData
-Objekt:
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Name | Wert |
---|---|
stoppen | Funktion ((id?: string) => void) |
Pause | Funktion ((id?: string) => void) |
Dauer | Zahl (oder null) |
Klang | Heulen (oder null) |
stop
ist eine Funktion, mit der Sie den Ton präventiv stoppen können.pause
ist wie stop
, außer dass es an derselben Stelle fortgesetzt werden kann. Sofern Sie nicht wissen, dass Sie fortfahren möchten, sollten Sie stop
verwenden; pause
beansprucht Ressourcen, da erwartet wird, dass es irgendwann wieder aufgenommen wird.duration
ist die Länge des Samples in Millisekunden. Es bleibt null
bis das Beispiel geladen wurde. Beachten Sie, dass es sich bei Sprites um die Länge der gesamten Datei handelt.sound
ist eine Notluke. Es gewährt Ihnen Zugriff auf die zugrunde liegende Howl
Instanz. Weitere Informationen zur Verwendung finden Sie in der Howler-Dokumentation. Beachten Sie, dass dieser Wert in den ersten Augenblicken nach der Bereitstellung der Komponente null
ist. Ein Audio-Sprite ist eine einzelne Audiodatei, die mehrere Samples enthält. Anstatt viele einzelne Sounds zu laden, können Sie eine einzelne Datei laden und sie in mehrere Abschnitte aufteilen, die unabhängig voneinander ausgelöst werden können.
Dies kann einen Leistungsvorteil mit sich bringen, da es weniger parallele Netzwerkanforderungen gibt, aber es kann sich auch lohnen, dies zu tun, wenn eine einzelne Komponente mehrere Samples benötigt. Ein Beispiel finden Sie in der Drum Machine-Geschichte.
Für Sprites müssen wir eine SpriteMap
definieren. Es sieht so aus:
const spriteMap = {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ;
SpriteMap
ist ein Objekt. Die Schlüssel sind die id
für einzelne Sounds. Der Wert ist ein Tupel (Array fester Länge) mit 2 Elementen:
Diese Visualisierung könnte es klarer machen:
Wir können unsere SpriteMap als eine unserer HookOptions übergeben:
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
Um ein bestimmtes Sprite abzuspielen, übergeben wir seine id
beim Aufruf der play
-Funktion:
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler ist eine sehr leistungsstarke Bibliothek, und wir haben in useSound
nur einen kleinen Ausschnitt ihrer Möglichkeiten offengelegt. Wir legen zwei Notluken frei, um Ihnen mehr Kontrolle zu geben.
Erstens wird jede nicht erkannte Option, die Sie an HookOptions
übergeben, an Howl
delegiert. Die vollständige Liste der Optionen finden Sie in den Howler-Dokumenten. Hier ist ein Beispiel dafür, wie wir onend
verwenden können, um eine Funktion auszulösen, wenn unser Sound nicht mehr abgespielt wird:
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
Wenn Sie mehr Kontrolle benötigen, sollten Sie das sound
direkt verwenden können, bei dem es sich um eine Instanz von Howler handelt.
Beispiel: Howler stellt eine fade
-Methode zur Verfügung, mit der Sie einen Sound ein- oder ausblenden können. Sie können diese Methode direkt am sound
aufrufen:
const Arcade = ( ) => {
const [ play , { sound } ] = useSound ( '/win-theme.mp3' ) ;
return (
< button
onClick = { ( ) => {
// You win! Fade in the victory theme
sound . fade ( 0 , 1 , 1000 ) ;
} }
>
Click to win
< / button >
) ;
} ;