如何在不重复上一首歌曲的情况下随机循环播放歌曲列表? (JavaScript)

时间:2020-01-07 21:45:28

标签: javascript audio

这是我在此处发布的上一个问题的后续问题。我已将其发布在这里,以防万一:How do I alter this function so that only one, random song can be played at a time with each click? (JavaScript)

我正在使用HTML / CSS / JavaScript构建此音乐生成器应用程序,其主要功能是,当用户单击代表音乐流派的特定图块时,该特定流派的一首歌曲就是一次播放。 感谢一些有帮助的SO用户,我能够构建一个可以帮助我做到这一点的功能:

let previousSong;
const randomizeSongs = playlist => {
    if (previousSong) {
        previousSong.pause();
        previousSong.currentTime = 0;
    }
    let song = playlist[Math.floor(Math.random() * playlist.length)];
    song.play();
    previousSong = song;
}

const pop = document.querySelector(".pop") // Div containing audio elements
pop.addEventListener("click", (e) => {
   let playlist = document.querySelectorAll(".pop audio")
   randomizeSongs(playlist);
 })

尽管此代码可以很好地工作,但我遇到的一个问题是,尽管歌曲是随机播放的,但即使多次单击,某些歌曲仍会反复播放,而其他歌曲则被忽略。在诸如Spotify或Apple Music之类的应用上,当您随机播放歌曲的播放列表时,歌曲 会随机播放,但是直到播放或跳过其他所有歌曲后,它们才会重复播放。

为解决此问题,我编写了以下代码:

  let previousSong;
  const randomizeSongs = playlist => {

    if (previousSong) {

      previousSong.pause();
      previousSong.currentTime = 0;

      let filteredPlaylist = playlist.filter(function(previousSong) {
        return !previousSong;
      })

      if (filteredPlaylist.length >= 1) {
        randomizeSongs(filteredPlaylist);
      }
      else {
        randomizeSongs(playlist);
      }
    }

    let song = playlist[Math.floor(Math.random() * playlist.length)];
    song.play();
    previousSong = song;

  }

我现在遇到了一个新问题。每当我单击代表音乐流派的特定div时,它都会随机选择一首歌曲,但是在第一次单击后每次单击都会使控制台返回:Uncaught TypeError: playlist.filter is not a function at randomizeSongs

我对自己做错的事情或我的代码朝正确的方向感到困惑。请帮忙。

2 个答案:

答案 0 :(得分:0)

let index = 0;
let previousSong = null;
let randomArray = null;

const randomizeSongs = playlist => {

    if(!randomArray) {
        toRandom(playlist);
    }

    if (previousSong) {

        previousSong.pause();
        previousSong.currentTime = 0;

    }

    if(index < randomArray.length) {
        const song = randomArray[index++];
        song.play();
        previousSong = song;
    }else {
        toRandom(playlist);
        index = 0;
        randomizeSongs(playlist);
    }
};

const toRandom = playlist => {

    const count = playlist.length;
    const playlist_copy = playlist.slice();
    randomArray = [];

    for(let i = 0; i < count; i++) {

        const rand = Math.floor( Math.random() * playlist_copy.length );

        randomArray.push(playlist_copy.splice(rand, 1))
    }

};

尝试

答案 1 :(得分:0)

您将生成一个包含所有音频元素的数组,并随机播放该数组。然后,在每次单击按钮时逐个循环遍历数组,直到到达末尾时才重新开始随机播放。我会使用randojs.com以一种简单易读的方式对数组进行洗牌。

var playlist = [];
var shuffledPlaylist = [];
var previousSong = false;

function playNextSong(){
    if(previousSong){
        previousSong.pause();
        previousSong.currentTime = 0;
    }

    if(shuffledPlaylist.length == 0) shuffledPlaylist = randoSequence(playlist);

    previousSong = shuffledPlaylist.pop().value;
    previousSong.play();
}

window.addEventListener('load', function(){
    playlist = document.querySelectorAll(".pop audio");
    document.querySelector(".pop").addEventListener("click", playNextSong);
});

如果要使用此代码,请将其包含在html文档的head标签中,以获取randojs功能的源代码:

<script src="https://randojs.com/1.0.0.js"></script>

否则,randoSequence(playlist)(改组playlist的函数调用)将不起作用。该代码还使用JavaScript的pop() function,它删除了shuffledPlaylist数组的最后一个元素并返回它,因此我们可以将值存储在previousSong变量中。