ウェブにはもっと(上品な)サウンドが必要です!
このライブラリは React DOM でのみ動作しますが、@remigallego が React Native の代替ライブラリを作成しました。反応ネイティブ使用サウンドを確認してください。
このプロジェクトは「半保守」ですか?
現時点では、エッジケースの問題を調査したり、トラブルシューティングを支援したりするための帯域幅はありませんが、メジャーな React リリースで最新の状態に保ち、深刻かつ一般的な問題を修正するつもりです。
機能に関するアイデアがある場合、または奇妙な癖に遭遇した場合は、プロジェクトをフォークして独自のものにすることを強くお勧めします。恐ろしいように思えるかもしれませんが、ソースは他の多くの NPM パッケージほど複雑ではありません。ハードなオーディオ作業はすべてハウラーに任せます)。 React をしばらく使用していて、フックに慣れている場合は、このパッケージのコードにすぐに慣れることができるはずです。
パッケージは、 yarn を使用して追加できます。
yarn add use-sound
または、NPM を使用します。
npm install use-sound
UMD ビルドは unpkg で利用可能です。
プロジェクトで TypeScript を使用する場合は、 @types/howler
パッケージも開発依存関係としてインストールする必要があります。
このチュートリアルには、多くのデモと、音響効果を見つけて準備するための手順が含まれています。始めるのに最適な場所です。
簡単な例が多数含まれているストーリーブックを参照することもできます。
import useSound from 'use-sound' ;
import boopSfx from '../../sounds/boop.mp3' ;
const BoopButton = ( ) => {
const [ play ] = useSound ( boopSfx ) ;
return < button onClick = { play } > Boop! < / button > ;
} ;
このデモでは、要素の上にマウスを移動している間のみサウンドが再生されます。マウスが要素から離れるとサウンドが一時停止します。
注: 多くのブラウザでは、ユーザーがページ上のどこかをクリックするまでサウンドが無効になります。この例で何も聞こえない場合は、どこかをクリックしてもう一度試してみてください。
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 >
) ;
} ;
playbackRate
オプションを使用すると、サンプルの速度/ピッチを変更できます。この例ではサウンドを再生し、毎回 10% 速くします。
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
はオーディオ ファイルへのパスが必要ですが、React アプリケーションでオーディオ ファイルへのパスを指定する方法は明らかではありません。
create-react-app
使用すると、MP3 ファイルを「インポート」できます。これは動的に生成されたパスに解決されます。
import someAudioFile from '../sounds/sound.mp3' ;
console . log ( someAudioFile ) ; // “/build/sounds/sound-abc123.mp3”
Next.js などの別の React ビルド システムでこのトリックを実行しようとすると、次のようなエラーが発生する可能性があります。
このファイル タイプを処理するには、適切なローダーが必要になる場合があります。現在、このファイルを処理するように構成されているローダーはありません。
問題は、Webpack (JS バンドルを生成するために内部的に使用されるバンドラー) が MP3 ファイルの処理方法を知らないことです。
Webpack 構成にアクセスできる場合は、ファイル ローダーを使用するように構成を更新できます。これにより、ファイルへの動的でパブリックにアクセス可能なパスが作成されます。
あるいは、ほとんどのツールでは、「パブリック」フォルダー (create-react-app、Next.js) または「静的」フォルダー (Gatsby) が提供されます。そこにオーディオ ファイルをドロップし、文字列パスを使用できます。
use-sound
で使用するサウンド ファイルは、画像やフォントなどの他の静的アセットと同じルールに従います。選択したメタフレームワークのガイドに従ってください。
️ 非同期サウンドパス?️ オーディオ ファイルへの URL が非同期で読み込まれる場合、いくつかの問題が発生する可能性があります。これはおそらく、そのユースケースには適切なパッケージではありません。
ユーザーのために、ブラウザでは、ユーザーが Web サイトと対話するまで (たとえば、何かをクリックするなど)、Web サイトがサウンドを生成することを許可しません。ユーザーがクリック、タップ、または何かをトリガーするまで、音は鳴りません。
useSound
これを利用します。サウンドは読み込み時にすぐには必要ないことがわかっているため、サードパーティの依存関係を遅延読み込みできます。
useSound
バンドルに約 1 kb gzip を追加し、ロード後に追加のパッケージを非同期でフェッチします。これにより、約 9 kb gzip がクロックインされます。
この依存関係がロードされてフェッチされる前に、ユーザーがノイズを発生する何かをクリックした場合、操作は行われません (すべてが引き続き動作しますが、効果音は再生されません)。私の経験では、これは非常にまれです。
次のコードの断片を考えてみましょう。
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
サウンドエフェクトの初期値として機能するだけではありません。 playbackRate
変更されると、サウンドはすぐに新しいレートで再生を開始します。これは、 useSound
フックに渡されるすべてのオプションに当てはまります。
useSound
フックは 2 つの引数を取ります。
HookOptions
)2 つの値を含む配列が生成されます。
ExposedData
)サウンドを再生する関数を呼び出すときに、一連のオプション ( PlayOptions
) を渡すことができます。
それぞれを順番に見ていきましょう。
useSound
を呼び出すときは、さまざまなオプションを渡すことができます。
名前 | 価値 |
---|---|
音量 | 番号 |
再生速度 | 番号 |
割り込み | ブール値 |
サウンド有効 | ブール値 |
スプライト | スプライトマップ |
[委任] | — |
volume
0
から1
までの数値です。1 1
最大音量、 0
完全にミュートです。playbackRate
0.5
~ 4
の数値です。サンプルの速度を遅くしたり速くしたりするために使用できます。ターンテーブルと同様に、速度の変化はピッチにも影響します。interrupt
サウンドが終了する前にplay
関数が再度呼び出された場合に、サウンドを「オーバーラップ」できるかどうかを指定します。soundEnabled
すると、すべてのサウンドをミュートする値 (通常はコンテキストや Redux などから) を渡すことができます。これはPlayOptions
でオーバーライドできることに注意してください。以下を参照してください。sprite
使用すると、複数のサウンド効果に対して単一のuseSound
フックを使用できます。以下の「スプライト」を参照してください。 [delegated]
HookOptions
に渡す追加の引数がHowl
コンストラクターに転送されるという事実を指します。詳細については、以下の「避難ハッチ」を参照してください。
play
機能フックを呼び出すと、タプルの最初の項目として再生関数が返されます。
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
サウンドをトリガーしたい場合は、引数なしでこの関数を呼び出すことができます。 PlayOptions
オブジェクトを使用して呼び出すこともできます。
名前 | 価値 |
---|---|
ID | 弦 |
強制サウンド有効化 | ブール値 |
再生速度 | 番号 |
id
スプライトの識別に使用されます。以下の「スプライト」を参照してください。forceSoundEnabled
、 HookOptions
に渡されるsoundEnabled
ブール値をオーバーライドできます。通常、これは決してやりたくないことです。私が見つけた唯一の例外は、「ミュート」ボタンでサウンドをトリガーすることです。playbackRate
、 HookOptions
と同様に、新しい再生レートを設定できるもう 1 つの方法です。一般的には、 HookOptions
使用してこれを行うことをお勧めします。これはエスケープハッチです。フックは、play 関数とExposedData
オブジェクトという 2 つのオプションを含むタプルを生成します。
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
名前 | 価値 |
---|---|
停止 | 関数 ((id?: 文字列) => void) |
一時停止 | 関数 ((id?: 文字列) => void) |
間隔 | 数値 (または null) |
音 | 遠吠え(またはヌル) |
stop
、サウンドを事前に停止するために使用できる機能です。pause
stop
と似ていますが、同じ時点から再開できる点が異なります。再開するかどうかわからない場合は、 stop
使用する必要があります。 pause
、ある時点で再開されることが予想されるため、リソースを大量に消費します。duration
サンプルの長さ (ミリ秒単位) です。サンプルがロードされるまではnull
になります。スプライトの場合、これはファイル全体の長さであることに注意してください。sound
脱出ハッチです。これにより、基礎となるHowl
インスタンスへのアクセスが許可されます。使用方法の詳細については、Howler のドキュメントを参照してください。コンポーネントがマウントされた後の最初の数分間は、これがnull
になることに注意してください。 オーディオ スプライトは、複数のサンプルを保持する単一のオーディオ ファイルです。多数の個別のサウンドをロードする代わりに、単一のファイルをロードして、独立してトリガーできる複数のセクションにスライスすることができます。
これにより、並列ネットワーク リクエストが少なくなるため、パフォーマンスが向上する可能性がありますが、単一のコンポーネントに複数のサンプルが必要な場合にもこれを実行する価値があります。例については、ドラムマシンのストーリーを参照してください。
スプライトの場合は、 SpriteMap
を定義する必要があります。次のようになります。
const spriteMap = {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ;
SpriteMap
オブジェクトです。キーは個々のサウンドのid
です。値は、2 つの項目を含むタプル (固定長の配列) です。
この視覚化により、次のことがより明確になる可能性があります。
SpriteMap を HookOptions の 1 つとして渡すことができます。
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
特定のスプライトを再生するには、 play
関数を呼び出すときにそのid
を渡します。
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler は非常に強力なライブラリですが、 useSound
で実行できる機能のほんの一部しか公開していません。より詳細に制御できるように、2 つの脱出ハッチを公開します。
まず、 HookOptions
に渡した認識されないオプションはすべてHowl
に委任されます。オプションの完全なリストは Howler のドキュメントで確認できます。以下は、サウンドの再生が停止したときにonend
使用して関数を起動する方法の例です。
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
さらに制御が必要な場合は、Howler のインスタンスであるsound
オブジェクトを直接使用できるはずです。
例: Howler は、サウンドをフェードインまたはフェードアウトできるfade
メソッドを公開します。このメソッドは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 >
) ;
} ;