【问题标题】:How would I randomly loop through a array/list of songs without repeating previous songs? (JavaScript)如何在不重复以前的歌曲的情况下随机循环播放歌曲数组/列表? (JavaScript)
【发布时间】:2020-01-08 06:21:00
【问题描述】:

这是我在此处发布的上一个问题的后续问题。我把它贴在这里以防万一: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

我对自己做错了什么感到困惑,或者我的代码是否朝着正确的方向前进。请帮忙。

【问题讨论】:

  • 在运行 randomizeSongs 之前播放列表的形状是什么?运行 randomizeSongs 之后是什么?
  • 不要随意选择歌曲。而是随机化你的整个列表,然后按顺序播放它们..
  • 请注意,您不需要像您一样将标签放在标题中。标签框用于标签。
  • 另外,研究“洗牌数组”。

标签: javascript audio


【解决方案1】:

您将生成一个包含所有音频元素的数组并打乱该数组。然后,在每个按钮单击时一个接一个地循环遍历数组,一旦到达末尾就更新随机播放。我会使用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 变量中。

【讨论】:

  • 感谢您的回答,但我还有一个问题。在代码中,您输入了 previousSong = shuffledPlaylist.pop().value;。现在我正在创建暂停/播放功能,我需要一个当前歌曲的变量,所以当用户按下空格键时,它会暂停或播放当前正在播放的歌曲,而不是之前播放过的任何歌曲.如何定义 currentSong 变量?
  • previousSong 真的是 currentSong,改名字就好了,
【解决方案2】:
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))
    }

};

试试看

【讨论】:

    猜你喜欢
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    相关资源
    最近更新 更多