Web membutuhkan lebih banyak suara (berselera)!
Pustaka ini hanya berfungsi dengan React DOM, tetapi @remigallego membuat alternatif untuk React Native! Lihat reaksi-penggunaan-asli.
Proyek ini “semi terpelihara”?
Saat ini saya tidak mempunyai bandwidth untuk menyelidiki permasalahan yang ada atau membantu memecahkan masalah, namun saya berencana untuk terus memperbaruinya dengan rilis-rilis utama React, dan memperbaiki masalah-masalah yang serius dan umum.
Jika Anda memiliki ide untuk fitur, atau mengalami keanehan yang aneh, saya sangat menyarankan untuk membuat proyek tersebut dan menjadikannya milik Anda sendiri! Ini mungkin tampak menakutkan, namun sumbernya tidak serumit banyak paket NPM lainnya; Saya menyerahkan semua kerja keras audio ke Howler). Jika Anda telah menggunakan React selama beberapa waktu dan merasa nyaman dengan hook, Anda akan merasa nyaman dengan kode paket ini.
Paket dapat ditambahkan menggunakan benang :
yarn add use-sound
Atau, gunakan NPM:
npm install use-sound
Pembuatan UMD tersedia di unpkg.
Jika proyek Anda menggunakan TypeScript, Anda juga harus menginstal paket @types/howler
sebagai ketergantungan dev.
Tutorialnya mencakup banyak demo, serta instruksi untuk menemukan dan menyiapkan efek suara. Ini adalah tempat yang bagus untuk memulai.
Anda juga dapat melihat buku cerita , yang berisi banyak contoh singkat.
import useSound from 'use-sound' ;
import boopSfx from '../../sounds/boop.mp3' ;
const BoopButton = ( ) => {
const [ play ] = useSound ( boopSfx ) ;
return < button onClick = { play } > Boop! < / button > ;
} ;
Demo ini hanya memutar suara sambil mengarahkan kursor ke suatu elemen. Suara berhenti ketika mouse meninggalkan elemen:
CATATAN: Banyak browser menonaktifkan suara hingga pengguna mengklik suatu tempat pada halaman. Jika Anda tidak mendengar apa pun pada contoh ini, coba klik di mana saja dan coba lagi.
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 >
) ;
} ;
Dengan opsi playbackRate
, Anda dapat mengubah kecepatan/pitch sampel. Contoh ini memutar suara dan membuatnya 10% lebih cepat setiap kali:
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
memerlukan jalur ke file audio, dan tidak jelas cara menyediakannya di aplikasi React.
Menggunakan create-react-app
, Anda dapat "mengimpor" file MP3. Ini akan menyelesaikan jalur yang dihasilkan secara dinamis:
import someAudioFile from '../sounds/sound.mp3' ;
console . log ( someAudioFile ) ; // “/build/sounds/sound-abc123.mp3”
Jika Anda mencoba melakukan trik ini di sistem build React lain seperti Next.js, Anda mungkin mendapatkan kesalahan seperti ini:
Anda mungkin memerlukan loader yang sesuai untuk menangani jenis file ini, saat ini tidak ada loader yang dikonfigurasi untuk memproses file ini.
Masalahnya adalah Webpack (bundel yang digunakan untuk menghasilkan bundel JS) tidak mengetahui cara memproses file MP3.
Jika Anda memiliki akses ke konfigurasi Webpack, Anda dapat memperbaruinya untuk menggunakan pemuat file, yang akan membuat jalur dinamis dan dapat diakses publik ke file tersebut.
Alternatifnya, sebagian besar alat akan memberi Anda folder "publik" (buat-reaksi-aplikasi, Next.js) atau "statis" (Gatsby). Anda dapat meletakkan file audio Anda di sana, lalu menggunakan jalur string.
File suara yang akan Anda gunakan dengan use-sound
mengikuti aturan yang sama seperti aset statis lainnya seperti gambar atau font. Ikuti panduan untuk kerangka meta pilihan Anda:
️ Jalur suara asinkron?️ Jika URL ke file audio Anda dimuat secara asinkron, Anda mungkin mengalami beberapa masalah. Ini mungkin bukan paket yang tepat untuk kasus penggunaan tersebut.
Demi pengguna, browser tidak mengizinkan situs web menghasilkan suara sampai pengguna berinteraksi dengannya (misalnya dengan mengklik sesuatu). Tidak ada suara yang dihasilkan sampai pengguna mengklik, mengetuk, atau memicu sesuatu.
useSound
mengambil keuntungan dari hal ini: karena kita tahu bahwa suara tidak akan dibutuhkan segera saat dimuat, kita dapat memuat ketergantungan pihak ketiga dengan lambat.
useSound
akan menambahkan sekitar 1kb gzip ke bundel Anda, dan secara asinkron akan mengambil paket tambahan setelah dimuat, yang memakan waktu sekitar 9kb gzip.
Jika pengguna mengklik sesuatu yang mengeluarkan suara sebelum ketergantungan ini dimuat dan diambil, maka tidak boleh dilakukan (semuanya akan tetap berfungsi, tetapi tidak ada efek suara yang akan diputar). Menurut pengalaman saya, hal ini sangat jarang terjadi.
Perhatikan cuplikan kode berikut:
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
tidak hanya berfungsi sebagai nilai awal untuk efek suara. Jika playbackRate
berubah, suara akan segera mulai diputar dengan kecepatan baru. Hal ini berlaku untuk semua opsi yang diteruskan ke kait useSound
.
Kait useSound
membutuhkan dua argumen:
HookOptions
)Ini menghasilkan array dengan dua nilai:
ExposedData
) Saat memanggil fungsi untuk memutar suara, Anda dapat memberikannya serangkaian opsi ( PlayOptions
).
Mari kita bahas masing-masing secara bergantian.
Saat memanggil useSound
, Anda dapat memberikannya berbagai opsi:
Nama | Nilai |
---|---|
volume | nomor |
Kecepatan pemutaran | nomor |
mengganggu | boolean |
suaraDiaktifkan | boolean |
sprite | Peta Sprite |
[didelegasikan] | — |
volume
adalah angka dari 0
hingga 1
, dengan 1
adalah volume penuh dan 0
sepenuhnya dibisukan.playbackRate
adalah angka dari 0.5
hingga 4
. Ini dapat digunakan untuk memperlambat atau mempercepat sampel. Seperti meja putar, perubahan kecepatan juga mempengaruhi nada.interrupt
menentukan apakah suara dapat "tumpang tindih" atau tidak jika fungsi play
dipanggil lagi sebelum suara berakhir.soundEnabled
memungkinkan Anda memberikan nilai (biasanya dari konteks atau redux atau semacamnya) untuk membisukan semua suara. Perhatikan bahwa ini dapat diganti di PlayOptions
, lihat di bawahsprite
memungkinkan Anda menggunakan satu useSound
hook untuk beberapa efek suara. Lihat “Sprite” di bawah. [delegated]
mengacu pada fakta bahwa argumen tambahan apa pun yang Anda sampaikan di HookOptions
akan diteruskan ke konstruktor Howl
. Lihat "Escape hatches" di bawah untuk informasi lebih lanjut.
play
Saat memanggil hook, Anda mendapatkan kembali fungsi play sebagai item pertama dalam tuple:
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Anda dapat memanggil fungsi ini tanpa argumen apa pun saat Anda ingin memicu suara. Anda juga dapat memanggilnya dengan objek PlayOptions
:
Nama | Nilai |
---|---|
pengenal | rangkaian |
forceSoundEnabled | boolean |
Kecepatan pemutaran | nomor |
id
digunakan untuk identifikasi sprite. Lihat “Sprite” di bawah.forceSoundEnabled
memungkinkan Anda mengganti boolean soundEnabled
yang diteruskan ke HookOptions
. Anda biasanya tidak ingin melakukan ini. Satu-satunya pengecualian yang saya temukan: memicu suara pada tombol "Bungkam".playbackRate
adalah cara lain untuk mengatur kecepatan pemutaran baru, sama seperti di HookOptions
. Secara umum Anda sebaiknya melakukannya melalui HookOptions
, ini adalah jalan keluar. Hook menghasilkan tupel dengan 2 opsi, fungsi play dan objek ExposedData
:
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Nama | Nilai |
---|---|
berhenti | fungsi ((id?: string) => batal) |
berhenti sebentar | fungsi ((id?: string) => batal) |
lamanya | nomor (atau nol) |
suara | Melolong (atau nol) |
stop
adalah fungsi yang dapat Anda gunakan untuk menghentikan suara terlebih dahulu.pause
itu seperti stop
, hanya saja dapat dilanjutkan dari titik yang sama. Kecuali Anda ingin melanjutkan, Anda harus menggunakan stop
; pause
sumber daya babi, karena diperkirakan akan dilanjutkan suatu saat nanti.duration
adalah panjang sampel, dalam milidetik. Ini akan menjadi null
sampai sampel dimuat. Perhatikan bahwa untuk sprite, ini adalah panjang keseluruhan file.sound
adalah jalan keluar. Ini memberi Anda akses ke instance Howl
yang mendasarinya. Lihat dokumentasi Howler untuk mempelajari lebih lanjut tentang cara menggunakannya. Perhatikan bahwa ini akan menjadi null
untuk beberapa saat pertama setelah komponen dipasang. Sprite audio adalah file audio tunggal yang menampung banyak sampel. Daripada memuat banyak suara individual, Anda dapat memuat satu file dan membaginya menjadi beberapa bagian yang dapat dipicu secara independen.
Hal ini dapat memberikan manfaat kinerja, karena permintaan jaringan paralelnya lebih sedikit, namun hal ini juga layak dilakukan jika satu komponen memerlukan banyak sampel. Lihat cerita Mesin Drum sebagai contoh.
Untuk sprite, kita perlu mendefinisikan SpriteMap
. Ini terlihat seperti ini:
const spriteMap = {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ;
SpriteMap
adalah sebuah objek. Kuncinya adalah id
untuk suara individual. Nilainya adalah tuple (array dengan panjang tetap) dengan 2 item:
Visualisasi ini mungkin membuatnya lebih jelas:
Kita dapat meneruskan SpriteMap kita sebagai salah satu HookOptions kita:
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
Untuk memainkan sprite tertentu, kami akan meneruskan id
saat memanggil fungsi play
:
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler adalah perpustakaan yang sangat kuat, dan kami hanya memperlihatkan sebagian kecil dari apa yang dapat dilakukannya di useSound
. Kami mengekspos dua pintu keluar untuk memberi Anda kontrol lebih besar.
Pertama, setiap opsi tidak dikenal yang Anda teruskan ke HookOptions
akan didelegasikan ke Howl
. Anda dapat melihat daftar lengkap opsi di dokumen Howler. Berikut ini contoh bagaimana kita dapat menggunakan onend
untuk mengaktifkan fungsi ketika suara kita berhenti diputar:
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
Jika Anda memerlukan kontrol lebih besar, Anda harus dapat menggunakan objek sound
secara langsung, yang merupakan turunan dari Howler.
Misalnya: Howler menampilkan metode fade
, yang memungkinkan Anda memudarkan suara masuk atau keluar. Anda dapat memanggil metode ini langsung pada objek 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 >
) ;
} ;