Интернету нужно больше (изящных) звуков!
Эта библиотека работает только с React DOM, но @remigallego создал альтернативу React Native! Проверьте реакцию-родной-использования-звук.
Этот проект «полуподдерживаемый»?
Сейчас у меня нет достаточной пропускной способности, чтобы изучать крайние проблемы или помогать устранять неполадки, но я планирую поддерживать ее в актуальном состоянии с основными выпусками React и исправлять как серьезные, так и распространенные проблемы.
Если у вас есть идеи по поводу функций или вы столкнулись со странными особенностями, я настоятельно рекомендую разветвить проект и сделать его собственным! Это может показаться пугающим, но исходный код не такой сложный, как у многих других пакетов NPM; Я перекладываю всю тяжелую работу со звуком на Хоулера). Если вы какое-то время используете React и вам знакомы хуки, вы должны чувствовать себя как дома с кодом этого пакета.
Пакет можно добавить с помощью пряжи :
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”
Если вы попытаетесь проделать этот трюк в другой системе сборки React, например Next.js, вы можете получить такую ошибку:
Для обработки этого типа файлов может потребоваться соответствующий загрузчик, в настоящее время ни один загрузчик не настроен для обработки этого файла.
Проблема в том, что Webpack (сборщик, используемый для создания пакетов JS) не знает, как обрабатывать файл MP3.
Если у вас есть доступ к конфигурации Webpack, вы можете обновить ее, чтобы использовать загрузчик файлов, который создаст динамический общедоступный путь к файлу.
Альтернативно, большинство инструментов предоставляют вам «общедоступную» (create-react-app, Next.js) или «статическую» (Gatsby) папку. Вы можете поместить туда свои аудиофайлы, а затем использовать строковый путь.
Звуковые файлы, которые вы будете использовать с use-sound
подчиняются тем же правилам, что и другие статические ресурсы, такие как изображения или шрифты. Следуйте инструкциям для выбранной вами мета-структуры:
️ Асинхронные звуковые пути?️ Если URL-адрес вашего аудиофайла загружается асинхронно, у вас могут возникнуть некоторые проблемы. Вероятно, это неподходящий пакет для этого варианта использования.
Ради пользователя браузеры не позволяют веб-сайтам воспроизводить звук до тех пор, пока пользователь не взаимодействует с ними (например, не нажимая на что-либо). Звук не будет воспроизводиться до тех пор, пока пользователь не щелкнет, не коснется или не активирует что-либо.
useSound
использует это в своих интересах: поскольку мы знаем, что звуки не понадобятся сразу при загрузке, мы можем отложенно загружать стороннюю зависимость.
useSound
добавит gzip размером около 1 КБ в ваш пакет и асинхронно получит дополнительный пакет после загрузки, который занимает около 9 КБ gzip.
Если пользователь нажмет на что-то, что издает шум, до того, как эта зависимость будет загружена и получена, это будет неактивно (все по-прежнему будет работать, но звуковой эффект не будет воспроизводиться). По моему опыту это крайне редко.
Рассмотрим следующий фрагмент кода:
const [ playbackRate , setPlaybackRate ] = React . useState ( 0.75 ) ;
const [ play ] = useSound ( '/path/to/sound' , { playbackRate } ) ;
playbackRate
не просто служит начальным значением звукового эффекта. Если playbackRate
изменится, звук немедленно начнет воспроизводиться с новой скоростью. Это верно для всех параметров, передаваемых в хук useSound
.
Хук useSound
принимает два аргумента:
HookOptions
)Он создает массив с двумя значениями:
ExposedData
). При вызове функции для воспроизведения звука вы можете передать ей набор параметров ( PlayOptions
).
Давайте пройдемся по каждому из них по очереди.
При вызове useSound
вы можете передать ему различные параметры:
Имя | Ценить |
---|---|
объем | число |
скорость воспроизведения | число |
прерывать | логическое значение |
звук включен | логическое значение |
спрайт | Карта спрайтов |
[делегирован] | — |
volume
— это число от 0
до 1
, где 1
— полная громкость, а 0
— полное отключение звука.playbackRate
— число от 0.5
до 4
. Его можно использовать для замедления или ускорения выборки. Как и в случае с проигрывателем, изменение скорости также влияет на высоту звука.interrupt
определяет, должен ли звук иметь возможность «перекрываться», если функция play
вызывается снова до того, как звук закончился.soundEnabled
позволяет вам передать значение (обычно из контекста, сокращения или чего-то еще), чтобы отключить все звуки. Обратите внимание, что это можно переопределить в PlayOptions
, см. ниже.sprite
позволяет вам использовать один хук useSound
для нескольких звуковых эффектов. См. «Спрайты» ниже. [delegated]
относится к тому факту, что любой дополнительный аргумент, который вы передаете в HookOptions
будет перенаправлен конструктору Howl
. Дополнительную информацию см. ниже в разделе «Аварийные люки».
play
При вызове перехватчика вы получаете функцию воспроизведения в качестве первого элемента кортежа:
const [ play ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Вы можете вызвать эту функцию без каких-либо аргументов, если хотите вызвать звук. Вы также можете вызвать его с помощью объекта PlayOptions
:
Имя | Ценить |
---|---|
идентификатор | нить |
ForceSoundEnabled | логическое значение |
скорость воспроизведения | число |
id
используется для идентификации спрайта. См. «Спрайты» ниже.forceSoundEnabled
позволяет вам переопределить логическое значение soundEnabled
, переданное в HookOptions
. Обычно вы никогда не захотите этого делать. Единственное исключение, которое я нашел: включение звука при нажатии кнопки «Отключить звук».playbackRate
— это еще один способ установить новую скорость воспроизведения, такой же, как в HookOptions
. В общем, лучше делать это через HookOptions
, это запасной выход. Хук создает кортеж с двумя опциями: функцией воспроизведения и объектом ExposedData
:
const [ play , exposedData ] = useSound ( '/meow.mp3' ) ;
// ^ What we're talking about
Имя | Ценить |
---|---|
останавливаться | функция ((id?: строка) => void) |
пауза | функция ((id?: строка) => void) |
продолжительность | число (или ноль) |
звук | Вой (или ноль) |
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
отдельных звуков. Значение представляет собой кортеж (массив фиксированной длины) с двумя элементами:
Эта визуализация может прояснить ситуацию:
Мы можем передать SpriteMap как один из наших HookOptions:
const [ play ] = useSound ( '/path/to/sprite.mp3' , {
sprite : {
laser : [ 0 , 300 ] ,
explosion : [ 1000 , 300 ] ,
meow : [ 2000 , 75 ] ,
} ,
} ) ;
Чтобы воспроизвести определенный спрайт, мы передаем его id
при вызове функции play
:
< button
onClick = { ( ) => play ( { id : 'laser' } ) }
>
Howler — очень мощная библиотека, и мы показали лишь малую часть того, что она может делать в useSound
. Мы открываем два аварийных люка, чтобы дать вам больше контроля.
Во-первых, любая нераспознанная опция, которую вы передаете в HookOptions
будет делегирована Howl
. Полный список опций вы можете увидеть в документации Howler. Вот пример того, как мы можем использовать onend
для запуска функции, когда наш звук перестает воспроизводиться:
const [ play ] = useSound ( '/thing.mp3' , {
onend : ( ) => {
console . info ( 'Sound ended!' ) ;
} ,
} ) ;
Если вам нужно больше контроля, вы сможете напрямую использовать sound
объект, который является экземпляром Howler.
Например: 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 >
) ;
} ;