显示不同数据的"上一个"和"下一个"按钮



我正在React/Redux中构建一个音乐播放器项目,并且上一个/下一个按钮有一些问题。。。我真的无法准确指出问题的原因,但以下是我的目标:

上一个按钮:应始终播放当前播放歌曲之前播放的最后一首歌曲。

下一个按钮:应该播放播放列表中的下一首歌曲。

我能够分别实现每个功能,这意味着如果我选择了n首歌曲,并点击了之前的n次(以任何顺序(,我就会得到之前播放的歌曲的正确列表。当我随机按下下一个和上一个按钮时,问题就出现了。我收到了一大堆乱七八糟的歌曲,而不是正确的顺序。

所以这是我的工作流程,只是为了让您更好地了解到目前为止这里发生的事情:

  1. 点击歌曲时-将当前歌曲对象作为调度动作发送到商店{current}
  2. 我们将当前选择的同一首歌曲发送到商店的previously_played阵列中,这样我们就有了以前播放歌曲的日志/历史记录
  3. 剩下的操作发生在下面显示的带有注释的dashboard.js文件中

我的目标:要让上一个按钮记录以前播放的所有歌曲,然后按下下一个按钮,应该会进入常规播放列表并播放歌曲。此外,如果当前歌曲是列表中的最后一首歌曲,则从播放列表中的第一首开始重新播放(反之亦然(。任何帮助都是很棒的家伙!提前谢谢。

我使用了redux,这是我的代码:

减速器:

import { CURRENT, PREV, NEXT, PLAYLIST, PREVIOUSLY_PLAYED } from '../actions/action_types';
const initial_state = {
playlist: [],
previously_played: [],
current_song: {},
prev_song: {},
next_song: {},
}
export default function songs_reducer (state = initial_state, action) {
switch(action.type) {
case PLAYLIST:
return {
...state,
playlist: action.payload
}
case PREVIOUSLY_PLAYED:
return {
...state,
previously_played: [...state.previously_played, action.payload]
}
case CURRENT:
return {
...state,
current_song: action.payload
}
case PREV:
return {
...state,
prev_song: action.payload
}
case NEXT:
return {
...state,
next_song: action.payload
}
default:
return state;
}
}

操作:

import { PLAYLIST, PREVIOUSLY_PLAYED, CURRENT, PREV, NEXT, CURRENT_ELEMENT } from './action_types';
export const playlist = data => ({
type: PLAYLIST,
payload: data
});
export const previously_played = data => ({
type: PREVIOUSLY_PLAYED,
payload: data
});
export const current = data => ({
type: CURRENT,
payload: data
});
export const prev = data => ({
type: PREV,
payload: data
});
export const next = data => ({
type: NEXT,
payload: data
});
export const current_element = data => ({
type: CURRENT_ELEMENT,
payload: data
});

行车记录仪:

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { playlist, previously_played, current, prev, next, current_element } from '../../redux/actions/actions';
// IMPORT COMPONENTS
import ControlsWidget from '../global/controls/controls.js';
import InfoWidget from '../global/info-widget/info_widget.js';
const Dashboard = (props) => {
const [playing_track, set_playing_track] = useState({}); // CURRENTLY PLAYING SONG

const [previous_song_name, set_previous_song_name] = useState('');
const [previous_song, set_previous_song] = useState('');
// COUNTER TO TRAVERSE BACKWARDS FOR PREVIOUS LOG
let [counter, set_counter] = useState(1);
// ON CURRENT TRACK UPDATE, SET THE CURRENTLY PLAYING TRACK DATA TO STATE, KEEPING IT GENERIC
useEffect(() => {       
set_playing_track({track: props.current_track.track, url: props.current_track.url});        
}, [props.current_track]);
// SHOW PREVIOUS SONG
const show_previous = () => {   
console.log('CURRENT TRACK (PREV BTN)', playing_track);
// console.log('PREVIOUSLY PLAYED SONGS', props.previously_played_songs);
counter++;
set_counter(counter);

let prev_url = props.previously_played_songs[props.previously_played_songs.length - (counter)].url;
let prev_track = props.previously_played_songs[props.previously_played_songs.length - (counter)].track;
// console.log('PREVIOUS SONG ', prev_url, prev_track);
set_playing_track({track: prev_track, url: prev_url});
// SET CURRENT
props.current(props.previously_played_songs[props.previously_played_songs.length - (counter)]);

}
// SHOW NEXT SONG
const show_next = () => {       
console.log('CURRENT TRACK (NXT BTN)', props.current_track);
// LOOP OVER PLAYLIST AND SET NEXT SONG
for (let i = 0; i < props.all_songs.length; i++) {          
if (((props.current_track.url.localeCompare(props.all_songs[i].url)) === 0)) {              

// SET AS CURRENT IN REDUX STORE
props.current(props.all_songs[i + 1]);              
// PUSH IN PREVIOUSLY PLAYED LOG
props.previously_played(props.all_songs[i + 1]);                
// SET AS CURRENTLY PLAYING GENERIC STATE VARIABLE
set_playing_track({track: props.all_songs[i + 1].track, url: props.all_songs[i + 1].url});                  
}
}
}
return (
<aside className='sec-std' id='main-dashboard'>         
<InfoWidget track_name={playing_track.track}/>
<ControlsWidget url={playing_track.url} show_previous={show_previous} show_next={show_next} />
</aside>
)
}
const mapStateToProps = (state) => {    
return {
current_track: state ? state.songs.current_song : null,
previously_played_songs: state ? state.songs.previously_played : null,
all_songs: state ? state.songs.playlist : null
}
}
export default connect(mapStateToProps, {current, previously_played})(Dashboard);

我认为这实际上是一个算法问题。

我认为我们需要先举一些例子。

假设播放列表是静态的,如[0,1,2,3,4,5,6,7]

然后假设用户可以随机播放任何歌曲,并且在当前歌曲结束后自动播放下一首歌曲。

现在考虑一些序列:

Step 1, play 4
=> history=[4], cur=4, prev=undefined, next=5
Step 2, just let 4 plays until the end, then 5 automatically plays, so that:
=> history=[4,5], cur=5, prev=4, next=6
Step 3, hit 7 before 5 ends
=> history=[4,5,7], cur=7, prev=5, next=8
Step 4, before 7 ends, hit 4 again
=> history=[5,7,4], cur=4, prev=7, next=5
Step 5, before 4 ends, hit prev, now 7 is the current song
=> history=[5,4,7], cur=7, prev=4, next=8
Step, before 7 ends, hit next, now 8 uis the current song
=> history=[5,4,7,8], cur=8, prev=7, next=undefined

不确定上面的例子是否符合您的要求?

如果是,那么算法是:

1. If the current song is not in history array, push it
2. Else if the current song in in history array, erase it, then push it
(So that current song is actually always history[length - 1])
3. So the prev song is actually always history[length - 2]
4. Next song is always playlist[current song's index +1]

相关内容

  • 没有找到相关文章

最新更新