A web precisa de mais sons (de bom gosto)!
Esta biblioteca só funciona com React DOM, mas @remigallego criou uma alternativa para React Native! Confira react-native-use-sound.
Este projeto é “semi-mantido” ?
Não tenho largura de banda no momento para analisar problemas extremos ou ajudar a solucionar problemas, mas pretendo mantê-lo atualizado com os principais lançamentos do React e corrigir problemas que são sérios e comuns.
Se você tiver ideias para recursos ou se deparar com peculiaridades estranhas, recomendo fortemente bifurcar o projeto e torná-lo seu! Pode parecer intimidante, mas a fonte não é tão complexa quanto muitos outros pacotes NPM; Deixo todo o trabalho pesado de áudio para Howler). Se você já usa o React há algum tempo e se sente confortável com ganchos, você deve se sentir em casa com o código deste pacote.
O pacote pode ser adicionado usando fio :
yarn add use-sound
Ou use NPM:
npm install use-sound
Compilação UMD disponível no unpkg.
Se o seu projeto usa TypeScript, você também deve instalar o pacote @types/howler
como uma dependência de desenvolvimento.
O tutorial inclui muitas demonstrações, bem como instruções para encontrar e preparar efeitos sonoros. É um ótimo lugar para começar.
Você também pode ver o livro de histórias , que inclui muitos exemplos 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 demonstração reproduz apenas o som enquanto você passa o mouse sobre um elemento. O som faz uma pausa quando o mouse sai do elemento:
NOTA: Muitos navegadores desativam os sons até que o usuário clique em algum lugar da página. Se você não estiver ouvindo nada com este exemplo, tente clicar em qualquer lugar e tente novamente.
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 >
) ;
} ;
Com a opção playbackRate
, você pode alterar a velocidade/afinação da amostra. Este exemplo reproduz um som e o torna 10% mais rápido a 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
requer um caminho para um arquivo de áudio e não é óbvio como fornecê-lo em um aplicativo React.
Usando create-react-app
, você pode "importar" um arquivo MP3. Ele será resolvido para um caminho gerado dinamicamente:
import someAudioFile from '../sounds/sound.mp3' ;
console . log ( someAudioFile ) ; // “/build/sounds/sound-abc123.mp3”
Se você tentar usar esse truque em outro sistema de compilação React como Next.js, poderá receber um erro como este:
Você pode precisar de um carregador apropriado para lidar com esse tipo de arquivo; atualmente, nenhum carregador está configurado para processar esse arquivo.
O problema é que o Webpack (o empacotador usado internamente para gerar pacotes JS) não sabe como processar um arquivo MP3.
Se você tiver acesso à configuração do Webpack, poderá atualizá-lo para usar o carregador de arquivos, que criará um caminho dinâmico e acessível ao público para o arquivo.
Como alternativa, a maioria das ferramentas fornecerá uma pasta “pública” (create-react-app, Next.js) ou “estática” (Gatsby). Você pode colocar seus arquivos de áudio lá e usar um caminho de string.
Os arquivos de som que você usará com use-sound
seguem as mesmas regras de outros ativos estáticos, como imagens ou fontes. Siga os guias da metaestrutura de sua escolha:
️ Caminhos de som assíncronos?️ Se o URL do seu arquivo de áudio for carregado de forma assíncrona, você poderá ter alguns problemas. Este provavelmente não é o pacote certo para esse caso.
Para o bem do usuário, os navegadores não permitem que os sites produzam som até que o usuário interaja com eles (por exemplo, clicando em algo). Nenhum som será produzido até que o usuário clique, toque ou acione algo.
useSound
tira vantagem disso: como sabemos que os sons não serão necessários imediatamente durante o carregamento, podemos carregar lentamente uma dependência de terceiros.
useSound
adicionará cerca de 1kb gzip ao seu pacote e buscará de forma assíncrona um pacote adicional após o carregamento, que atinge cerca de 9kb gzip.
Se o usuário clicar em algo que faça barulho antes que essa dependência seja carregada e buscada, não será operacional (tudo ainda funcionará, mas nenhum efeito sonoro será reproduzido). Na minha experiência, isso é extremamente raro.
Considere o seguinte trecho de código:
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
não serve apenas como valor inicial para o efeito sonoro. Se playbackRate
for alterada, o som começará imediatamente a ser reproduzido em uma nova taxa. Isso é verdade para todas as opções passadas para o gancho useSound
.
O gancho useSound
leva dois argumentos:
HookOptions
)Produz um array com dois valores:
ExposedData
) Ao chamar a função para reproduzir o som, você pode passar um conjunto de opções ( PlayOptions
).
Vamos examinar cada um deles por vez.
Ao chamar useSound
, você pode passar uma variedade de opções:
Nome | Valor |
---|---|
volume | número |
taxa de reprodução | número |
interromper | booleano |
som habilitado | booleano |
ator | SpriteMap |
[delegado] | - |
volume
é um número de 0
a 1
, onde 1
é o volume máximo e 0
é completamente silenciado.playbackRate
é um número de 0.5
a 4
. Pode ser usado para desacelerar ou acelerar a amostra. Como uma plataforma giratória, as mudanças na velocidade também afetam o tom.interrupt
especifica se o som deve ou não ser capaz de "se sobrepor" se a função play
for chamada novamente antes do som terminar.soundEnabled
permite que você passe um valor (normalmente de contexto ou redux ou algo assim) para silenciar todos os sons. Observe que isso pode ser substituído em PlayOptions
, veja abaixosprite
permite que você use um único gancho useSound
para vários efeitos sonoros. Veja “Sprites” abaixo. [delegated]
refere-se ao fato de que qualquer argumento adicional que você passar em HookOptions
será encaminhado para o construtor Howl
. Consulte "Saídas de emergência" abaixo para obter mais informações.
play
Ao chamar o gancho, você recebe de volta uma função play como o primeiro item da tupla:
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Você pode chamar esta função sem nenhum argumento quando quiser acionar o som. Você também pode chamá-lo com um objeto PlayOptions
:
Nome | Valor |
---|---|
eu ia | corda |
forceSoundEnabled | booleano |
taxa de reprodução | número |
id
é usado para identificação de sprites. Veja “Sprites” abaixo.forceSoundEnabled
permite substituir o booleano soundEnabled
passado para HookOptions
. Você geralmente nunca quer fazer isso. A única exceção que encontrei: acionar um som no botão “Mudo”.playbackRate
é outra maneira de definir uma nova taxa de reprodução, igual a HookOptions
. Em geral você deve preferir fazer isso através de HookOptions
, esta é uma saída de emergência. O gancho produz uma tupla com 2 opções, a função play e um objeto ExposedData
:
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Nome | Valor |
---|---|
parar | função ((id?: string) => vazio) |
pausa | função ((id?: string) => vazio) |
duração | número (ou nulo) |
som | Uivo (ou nulo) |
stop
é uma função que você pode usar para interromper preventivamente o som.pause
é como stop
, exceto que pode ser retomado do mesmo ponto. A menos que você saiba que deseja retomar, use stop
; pause
consome recursos, pois espera ser retomado em algum momento.duration
é a duração da amostra, em milissegundos. Será null
até que a amostra seja carregada. Observe que para sprites, é o comprimento do arquivo inteiro.sound
é uma saída de emergência. Ele concede acesso à instância subjacente Howl
. Consulte a documentação do Howler para saber mais sobre como usá-lo. Observe que isso será null
nos primeiros momentos após a montagem do componente. Um sprite de áudio é um único arquivo de áudio que contém várias amostras. Em vez de carregar muitos sons individuais, você pode carregar um único arquivo e dividi-lo em várias seções que podem ser acionadas de forma independente.
Pode haver um benefício de desempenho nisso, já que são menos solicitações de rede paralelas, mas também pode valer a pena fazer isso se um único componente precisar de várias amostras. Veja a história da Drum Machine como exemplo.
Para sprites, precisaremos definir um SpriteMap
. Parece assim:
const spriteMap = {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ;
SpriteMap
é um objeto. As chaves são os id
s para sons individuais. O valor é uma tupla (matriz de comprimento fixo) com 2 itens:
Esta visualização pode deixar isso mais claro:
Podemos passar nosso SpriteMap como uma de nossas HookOptions:
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
Para reproduzir um sprite específico, passaremos seu id
ao chamar a função play
:
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler é uma biblioteca muito poderosa e expusemos apenas uma pequena fatia do que ela pode fazer em useSound
. Expomos duas escotilhas de fuga para lhe dar mais controle.
Primeiro, qualquer opção não reconhecida que você passar para HookOptions
será delegada a Howl
. Você pode ver a lista completa de opções na documentação do Howler. Aqui está um exemplo de como podemos usar onend
para disparar uma função quando nosso som para de tocar:
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
Se precisar de mais controle, você poderá usar o objeto sound
diretamente, que é uma instância do Howler.
Por exemplo: Howler expõe um método fade
, que permite aumentar ou diminuir o som. Você pode chamar esse método diretamente no 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 >
) ;
} ;