如何处理React& amp;中的音频播放Redux [英] How to handle Audio playing in React & Redux

查看:67
本文介绍了如何处理React& amp;中的音频播放Redux的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作音频播放器.它具有暂停,倒带和时间搜索功能.如何以及由谁来处理音频元素?

I am making an audio player. It has pause, rewind and time seek features. How and who should handle the audio element?

  • 我可以把它放在商店那边.我无法将其直接放在状态上,因为它可能会被克隆.然后,在减速器中,我可以与其进行交互.问题是,如果我需要将时间滑块与音频同步,则需要使用动作来不断地轮询商店.从语义上讲,这也没有任何意义.
  • 我可以创建一个自定义的React组件Audio,它可以完成我所说的一切.问题没有解决.如何刷新滑块?我可以投票,但我真的不喜欢这种解决方案.此外,除非我创建一个既包含音频又包含滑块的组件,否则我仍然需要使用redux来连接两者.

那么使用进度显示处理音频的最主要的方法是什么?

So what is the most redux way to handle audio with progress display?

推荐答案

Redux-一切都与状态和一致性有关.

Redux - it's all about the state and consistency.

您的目标是使歌曲时间和进度条保持同步.

Your goal is to keep in sync the song time and the progress bar.

我看到两个可能的解决方法:

I see two possible aproaches:

因此,由于有一些依赖组件,并且如果没有商店就很难同步歌曲,因此您必须将歌曲的当前时间(例如,以秒为单位)保存在商店中.

So you have to keep the song's current time (in seconds for instance) in the Store, because of there are a few dependend components and its hard to sync them without the Store.

您很少会更改当前时间的事件:

You have few events those change the current time:

  • 当前时间本身.例如,每1秒.
  • 倒带
  • 时间搜寻.

在时间更改时,您将分派操作并使用新时间更新商店.从而保持当前歌曲的时间,所有组件将保持同步.

On a time change you will dispatch an action and will update the Store with the new time. Thereby keeping current song's time all components will be in sync.

通过动作分派,缩减器和存储来管理单向数据流中的状态是实现任何组件的Redux方法.

Managing the state in unidirectional data flow with actions dispatching, reducers and stores is the Redux way of implementing any component.

这是#1方法的伪代码:

Here is a pseudo code of the #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.尽量减少存放在商店中.

如果上述方法不符合您的需求,例如,您可能在同一屏幕上有很多音频播放器-可能会有性能差距.


2. Keep as less as possible in the Store.

If the above aproach doesn't fit your needs, for example you may have a lot of Audio players on a same screen - there may be a performance gap.

在这种情况下,您可以通过 refs .

In that case you can access your HTML5 audio tag and components via refs in the componentDidMount lifecycle method.

HTML5音频标签具有DOM事件,您可以在不触摸商店的情况下使两个组件保持同步.如果需要在商店中保存某些东西,您可以随时进行.

The HTML5 audio tag has DOM events and you can keep the both components in sync without touching the Store. If there is a need to save something in the Store - you can do it anytime.

请查看反应音频播放器源代码,并检查其如何处理引用以及插件公开的API.当然,您可以从那里得到启发.您也可以将其重新用于您的用例.

Please take a look at react-audio-player source code and check how it handles the refs and what API the plugin exposes. For sure you can take inspiration from there. Also you can reuse it for your use case.

以下是一些与您的问题相关的API方法:

Here are some of the API methods those are related to your questions:

  • onSeeked-在用户将时间指示器拖动到新时间时调用.通过了活动.
  • onPlay-在用户点击播放时调用.通过了活动.
  • onPause-在用户暂停播放时调用.通过了活动.
  • onListen-播放期间每隔listenInterval毫秒调用一次.通过了活动.

这取决于您的用例细节.但是,一般来讲,在这两种方法中,最好实现表示性组件以及必要的API方法,由您决定要在商店中管理多少数据.

It depends to your use case specifics. However generally speaking in the both aproaches it's a good idea to implement a presentational component with the necessary API methods and it's up to you to decide how much data to manage in the Store.

因此,我为您创建了一个开始组件,以说明如何处理对音频和滑块的引用.包括开始/停止/搜索功能.当然,它有缺点,但是正如我已经提到的,这是一个很好的起点.

So I created a starting component for you to illustrate how to handle the refs to the audio and slider. Start / Stop / Seeking features included. For sure it has drawbacks, but as I already mentioned it's a good starting point.

您可以使用适合您需要的API方法将其发展为演示组件.

You can evolve it to a presentational component with good API methods, that suits your needs.

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://mp3.gisher.org/download/1000/preview/true";
		
		
		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>

如果您有任何疑问,请在下面发表评论! :)

If you have any questions feel free to comment below! :)

这篇关于如何处理React&amp; amp;中的音频播放Redux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆