¡La web necesita más sonidos (de buen gusto)!
¡Esta biblioteca solo funciona con React DOM, pero @remigallego creó una alternativa para React Native! Echa un vistazo a reaccionar-nativo-uso-sonido.
¿Este proyecto está “semi-mantenido”?
No tengo el ancho de banda en este momento para investigar problemas extremos o ayudar a solucionar problemas, pero planeo mantenerlo actualizado con las principales versiones de React y solucionar problemas que son tanto graves como comunes.
Si tienes ideas para funciones o te encuentras con peculiaridades extrañas, te recomiendo bifurcar el proyecto y hacerlo tuyo. Puede parecer intimidante, pero el código fuente no es tan complejo como el de muchos otros paquetes de NPM; Dejo todo el arduo trabajo de audio en manos de Howler). Si ha estado usando React por un tiempo y se siente cómodo con los ganchos, debería sentirse como en casa con el código de este paquete.
El paquete se puede agregar usando hilo :
yarn add use-sound
O utilice NPM:
npm install use-sound
Compilación UMD disponible en unpkg.
Si su proyecto usa TypeScript, también debe instalar el paquete @types/howler
como una dependencia de desarrollo.
El tutorial incluye muchas demostraciones, así como instrucciones para buscar y preparar efectos de sonido. Es un gran lugar para empezar.
También puedes ver el libro de cuentos , que incluye muchos ejemplos rápidos.
import useSound from 'use-sound' ;
import boopSfx from '../../sounds/boop.mp3' ;
const BoopButton = ( ) => {
const [ play ] = useSound ( boopSfx ) ;
return < button onClick = { play } > Boop! < / button > ;
} ;
Esta demostración solo reproduce el sonido al pasar el cursor sobre un elemento. El sonido se detiene cuando el mouse abandona el elemento:
NOTA: Muchos navegadores desactivan los sonidos hasta que el usuario haya hecho clic en algún lugar de la página. Si no escucha nada con este ejemplo, intente hacer clic en cualquier lugar y vuelva a intentarlo.
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 >
) ;
} ;
Con la opción playbackRate
, puedes cambiar la velocidad/tono de la muestra. Este ejemplo reproduce un sonido y lo hace un 10% más rápido cada vez:
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
requiere una ruta a un archivo de audio y no es obvio cómo proporcionar una en una aplicación React.
Usando create-react-app
, puedes "importar" un archivo MP3. Se resolverá en una ruta generada dinámicamente:
import someAudioFile from '../sounds/sound.mp3' ;
console . log ( someAudioFile ) ; // “/build/sounds/sound-abc123.mp3”
Si intenta realizar este truco en otro sistema de compilación de React como Next.js, puede recibir un error como este:
Es posible que necesite un cargador adecuado para manejar este tipo de archivo; actualmente no hay cargadores configurados para procesar este archivo.
El problema es que Webpack (el paquete utilizado para generar paquetes JS) no sabe cómo procesar un archivo MP3.
Si tiene acceso a la configuración de Webpack, puede actualizarla para usar el cargador de archivos, que creará una ruta dinámica y de acceso público al archivo.
Alternativamente, la mayoría de las herramientas le brindarán una carpeta "pública" (create-react-app, Next.js) o "estática" (Gatsby). Puede colocar sus archivos de audio allí y luego usar una ruta de cadena.
Los archivos de sonido que usarás con use-sound
siguen las mismas reglas que otros recursos estáticos como imágenes o fuentes. Siga las guías para el metamarco de su elección:
️ ¿Rutas de sonido asíncronas?️ Si la URL de su archivo de audio se carga de forma asincrónica, es posible que tenga algunos problemas. Probablemente este no sea el paquete adecuado para ese caso de uso.
Por el bien del usuario, los navegadores no permiten que los sitios web produzcan sonido hasta que el usuario haya interactuado con ellos (por ejemplo, al hacer clic en algo). No se producirá ningún sonido hasta que el usuario haga clic, toque o active algo.
useSound
aprovecha esto: como sabemos que los sonidos no serán necesarios inmediatamente en la carga, podemos cargar de forma diferida una dependencia de terceros.
useSound
agregará aproximadamente 1 kb de gzip a su paquete y buscará de forma asincrónica un paquete adicional después de la carga, que registra alrededor de 9 kb de gzip.
Si el usuario hace clic en algo que hace ruido antes de que se haya cargado y recuperado esta dependencia, no será posible (todo seguirá funcionando, pero no se reproducirá ningún efecto de sonido). En mi experiencia esto es extremadamente raro.
Considere el siguiente fragmento de código:
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
no sirve solo como valor inicial para el efecto de sonido. Si playbackRate
cambia, el sonido comenzará a reproducirse inmediatamente a una nueva velocidad. Esto es cierto para todas las opciones pasadas al gancho useSound
.
El gancho useSound
toma dos argumentos:
HookOptions
)Produce una matriz con dos valores:
ExposedData
) Al llamar a la función para reproducir el sonido, puede pasarle un conjunto de opciones ( PlayOptions
).
Repasemos cada uno de estos por turno.
Al llamar useSound
, puedes pasarle una variedad de opciones:
Nombre | Valor |
---|---|
volumen | número |
velocidad de reproducción | número |
interrumpir | booleano |
sonido habilitado | booleano |
duende | Mapa de Sprites |
[delegado] | — |
volume
es un número del 0
al 1
, donde 1
es el volumen completo y 0
está completamente silenciado.playbackRate
es un número del 0.5
al 4
. Se puede utilizar para ralentizar o acelerar la muestra. Al igual que un tocadiscos, los cambios de velocidad también afectan el tono.interrupt
especifica si el sonido debe poder "superponerse" o no si se llama nuevamente a la función play
antes de que finalice el sonido.soundEnabled
le permite pasar un valor (normalmente de contexto o redux o algo así) para silenciar todos los sonidos. Tenga en cuenta que esto se puede anular en PlayOptions
, ver más abajosprite
te permite usar un gancho de sonido de un solo useSound
para múltiples efectos de sonido. Consulta "Sprites" a continuación. [delegated]
se refiere al hecho de que cualquier argumento adicional que pase en HookOptions
se reenviará al constructor Howl
. Consulte "Trampillas de escape" a continuación para obtener más información.
play
Al llamar al gancho, obtienes una función de reproducción como primer elemento de la tupla:
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Puede llamar a esta función sin ningún argumento cuando desee activar el sonido. También puedes llamarlo con un objeto PlayOptions
:
Nombre | Valor |
---|---|
identificación | cadena |
fuerzaSonidoEnabled | booleano |
tasa de reproducción | número |
id
se utiliza para la identificación de sprites. Consulta "Sprites" a continuación.forceSoundEnabled
le permite anular el booleano soundEnabled
pasado a HookOptions
. Generalmente nunca querrás hacer esto. La única excepción que encontré: activar un sonido con el botón "Silenciar".playbackRate
es otra forma de establecer una nueva velocidad de reproducción, igual que en HookOptions
. En general, deberías preferir hacerlo a través de HookOptions
, esta es una trampilla de escape. El gancho produce una tupla con 2 opciones, la función play y un objeto ExposedData
:
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Nombre | Valor |
---|---|
detener | función ((id?: cadena) => vacío) |
pausa | función ((id?: cadena) => vacío) |
duración | número (o nulo) |
sonido | Aullido (o nulo) |
stop
es una función que puede utilizar para detener preventivamente el sonido.pause
es como stop
, excepto que se puede reanudar desde el mismo punto. A menos que sepa que desea continuar, debe usar stop
; pause
acapara los recursos, ya que se espera que se reanude en algún momento.duration
es la longitud de la muestra, en milisegundos. Será null
hasta que se haya cargado la muestra. Tenga en cuenta que para los sprites, es la longitud de todo el archivo.sound
es una trampilla de escape. Le otorga acceso a la instancia subyacente Howl
. Consulte la documentación de Howler para obtener más información sobre cómo usarlo. Tenga en cuenta que esto será null
durante los primeros momentos después de que se monte el componente. Un sprite de audio es un único archivo de audio que contiene varias muestras. En lugar de cargar muchos sonidos individuales, puedes cargar un solo archivo y dividirlo en varias secciones que se pueden activar de forma independiente.
Esto puede generar un beneficio de rendimiento, ya que se trata de menos solicitudes de red paralelas, pero también puede valer la pena hacerlo si un solo componente necesita varias muestras. Vea la historia de Drum Machine para ver un ejemplo.
Para sprites, necesitaremos definir un SpriteMap
. Se parece a esto:
const spriteMap = {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ;
SpriteMap
es un objeto. Las claves son las id
de sonidos individuales. El valor es una tupla (matriz de longitud fija) con 2 elementos:
Esta visualización podría aclararlo:
Podemos pasar nuestro SpriteMap como una de nuestras HookOptions:
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
Para reproducir un objeto específico, pasaremos su id
al llamar a la función play
:
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler es una biblioteca muy poderosa y solo hemos expuesto una pequeña porción de lo que puede hacer en useSound
. Exponemos dos trampillas de escape para darle más control.
Primero, cualquier opción no reconocida que pase a HookOptions
se delegará a Howl
. Puede ver la lista completa de opciones en los documentos de Howler. Aquí hay un ejemplo de cómo podemos usar onend
para activar una función cuando nuestro sonido deja de reproducirse:
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
Si necesita más control, debería poder utilizar el objeto sound
directamente, que es una instancia de Howler.
Por ejemplo: Howler expone un método fade
, que le permite atenuar o atenuar un sonido. Puedes llamar a este método directamente en el objeto sound
:
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 >
) ;
} ;