Как обрабатывать воспроизведение звука в React & Redux
Я делаю аудиоплеер. Он имеет паузу, перемотку назад и функции поиска времени. Как и кто должен обрабатывать аудиоэлемент?
- Я могу отложить его в сторону магазин. Я не могу поставить его прямо на государство, так как он может быть клонирован. Тогда, когда в редукторе я могу взаимодействовать с ним. Проблема в том, что если мне нужно синхронизировать слайдер времени со звуком, мне нужно будет постоянно опрашивать магазин с помощью действия. Это также не имеет смысла семантически разговор.
- Я могу создать пользовательский компонент React, Audio, который делает все, что я сказал. проблема не решена. Как обновить слайдер? Я мог бы опросить, но мне действительно не нравится это решение. Кроме того, если я не создам компонент, содержащий аудио и слайдер, мне все равно нужно будет использовать redux для подключения обоих.
Итак, каков наиболее редукс способ обработки звука с дисплеем прогресса?
1 ответов
Redux - это все о состоянии и последовательности.
ваша цель состоит в том, чтобы синхронизировать время песни и индикатор выполнения.
Я вижу два возможных приближения:
1. Держать все в магазине.
таким образом, вы должны сохранить текущее время песни (в секундах, например) в магазине, потому что есть несколько зависимых компонентов и его трудно синхронизировать их без магазина.
У вас есть несколько событий, которые изменяют текущий время:
- само текущее время. Например, на каждую 1 секунду.
- "назад".
- времени искать.
при изменении времени вы отправите действие и обновите магазин с новым временем. Таким образом, сохраняя время текущей песни, все компоненты будут синхронизированы.
управление состоянием в однонаправленном потоке данных с диспетчеризацией действий, редукторами и хранилищами является способом Redux реализации любого деталь.
вот псевдо-код # 1 aproach:
class AudioPlayer extends React.Component {
onPlay(second) {
// Store song current time in the Store on each one second
store.dispatch({ type: 'SET_CURRENT_SECOND', second });
}
onRewind(seconds) {
// Rewind song current time
store.dispatch({ type: 'REWIND_CURRENT_SECOND', seconds });
}
onSeek(seconds) {
// Seek song current time
store.dispatch({ type: 'SEEK_CURRENT_SECOND', seconds });
}
render() {
const { currentTime, songLength } = this.state;
return <div>
<audio onPlay={this.onPlay} onRewind={this.onRewind} onSeek={this.onSeek} />
<AudioProgressBar currentTime songLength />
</div>
}
}
2. Держите как можно меньше в магазине.
если вышеуказанный aproach не соответствует вашим потребностям, например, у вас может быть много аудиоплееров на одном экране - может быть разрыв в производительности.
в этом случае вы можете получить доступ к тегу и компонентам HTML5 audio через refs в методе жизненного цикла componentDidMount.
аудио тег HTML5 имеет события DOM, и вы можете синхронизировать оба компонента, не касаясь магазина. Если есть необходимость сохранить что-то в магазине - вы можете сделать это в любое время.
пожалуйста, взгляните на react-исходный код аудиоплеера и проверьте, как он обрабатывает ссылки и какой API предоставляет плагин. Конечно, вы можете взять вдохновение оттуда. Также вы можете использовать его для вашего случая.
вот некоторые из методов API, которые связаны с вашим вопросы:
- onSeeked-вызывается, когда пользователь перетаскивает индикатор времени в Новое время. Прошло мероприятие.
- onPlay-вызывается, когда пользователь нажимает play. Прошло мероприятие.
- onPause-вызывается, когда пользователь приостанавливает воспроизведение. Прошло мероприятие.
- onListen-вызывается каждый listenInterval миллисекунд во время воспроизведения. Прошло мероприятие.
какой подход я должен использовать?
Это зависит от вашей особенности прецедентов. Однако, вообще говоря, в обоих aproaches это хорошая идея реализовать презентационная составляющая с необходимыми методами API, и это до вас, чтобы решить, сколько данных для управления в магазине.
поэтому я создал начальный компонент для вас, чтобы проиллюстрировать, как обрабатывать ссылки на аудио и слайдер. Start / Stop / Поиск функций включены. Конечно, у него есть недостатки, но, как я уже упоминал, это хорошее начало точка.
вы можете развить его в презентационный компонент с хорошими методами API, который соответствует вашим потребностям.
class Audio extends React.Component {
constructor(props) {
super(props);
this.state = {
duration: null
}
};
handlePlay() {
this.audio.play();
}
handleStop() {
this.audio.currentTime = 0;
this.slider.value = 0;
this.audio.pause();
}
componentDidMount() {
this.slider.value = 0;
this.currentTimeInterval = null;
// Get duration of the song and set it as max slider value
this.audio.onloadedmetadata = function() {
this.setState({duration: this.audio.duration});
}.bind(this);
// Sync slider position with song current time
this.audio.onplay = () => {
this.currentTimeInterval = setInterval( () => {
this.slider.value = this.audio.currentTime;
}, 500);
};
this.audio.onpause = () => {
clearInterval(this.currentTimeInterval);
};
// Seek functionality
this.slider.onchange = (e) => {
clearInterval(this.currentTimeInterval);
this.audio.currentTime = e.target.value;
};
}
render() {
const src = "https://files.freemusicarchive.org/music%2Fno_curator%2FThe_Womb%2FBang_-_An_Introduction_to_The_Womb%2FThe_Womb_-_02_-_Sex_Club.mp3";
return <div>
<audio ref={(audio) => { this.audio = audio }} src={src} />
<input type="button" value="Play"
onClick={ this.handlePlay.bind(this) } />
<input type="button"
value="Stop"
onClick={ this.handleStop.bind(this) } />
<p><input ref={(slider) => { this.slider = slider }}
type="range"
name="points"
min="0" max={this.state.duration} /> </p>
</div>
}
}
ReactDOM.render(<Audio />, document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Если у вас есть какие-либо вопросы, не стесняйтесь комментировать ниже! :)