【问题标题】:Convert this JavaScript to work with multiple songs?将此 JavaScript 转换为处理多首歌曲?
【发布时间】:2013-03-04 05:14:52
【问题描述】:

我创建了这个小音频播放器,它播放随机的前奏、歌曲的中段和随机的结尾。 现在它被硬编码为一首歌曲。每首歌有 3 个前奏、一个中段和 3 个结尾。我希望能够有一个随机选择的歌曲列表(例如从数组中随机选择),因此脚本将选择一首歌曲并相应地更改脚本(前奏和结尾以及中段)。 我考虑了不同的方法来做到这一点,但我不希望脚本中的每首歌曲都有大量的数组。我将如何设计这样的系统? www.saradio.tk/dev.html 的演示(音频计时仅在 Chrome-ACTIVE-TAB AFAIK 中正常工作)

代码:

<body onload="checkdif(), loadintro(), loadoutro()">
<audio id="intro" src="" controls preload autoplay></audio>
<audio id="mid" src="radio/Barracuda-mid.ogg" controls preload></audio>
<audio id="outro" src="" controls preload></audio>
<br>
<br>
<button onclick="resetradio()">RESET</button>   <span id="timeleft"> n/a </span>

<script>
    var intros = [
        "radio/Barracuda-intro1.ogg",
        "radio/Barracuda-intro2.ogg",
        "radio/Barracuda-intro3.ogg"];

    var outros = [
        "radio/Barracuda-outro1.ogg",
        "radio/Barracuda-outro2.ogg",
        "radio/Barracuda-outro3.ogg"];

    function loadintro() {
        document.getElementById("intro").src = intros[Math.floor(Math.random() * intros.length)];
        document.getElementById("intro").load();
        document.getElementById("intro").play();
    }

    function loadoutro() {
        document.getElementById("outro").src = outros[Math.floor(Math.random() * outros.length)];
        document.getElementById("outro").load();
    }

    x = document.getElementById('intro');
    y = document.getElementById('mid');
    done = false;
    done2 = false;

    function checkdif() {
        if (done) return;
        setTimeout('checkdif()', 5);
        document.getElementById('timeleft').innerHTML = x.duration - x.currentTime;
        if (x.duration - x.currentTime <= 0.09) {
            document.getElementById('mid').play();
            done = true;
            checkdif2();
        }
    }

    function checkdif2() {
        if (done2) return;
        setTimeout('checkdif2()', 5);
        document.getElementById('timeleft').innerHTML = y.duration - y.currentTime;
        if (y.duration - y.currentTime <= 0.09) {
            document.getElementById('outro').play();
            done2 = true;
        }
    }

    function resetradio() {
        done = false;
        done2 = false;
        document.getElementById('mid').pause();
        document.getElementById('mid').currentTime = 0;
        loadintro();
        loadoutro();
        checkdif();
    }

    document.getElementById("outro").addEventListener('ended', resetradio, false)
</script>
</body>

PS:我还考虑过设计系统,以便将刚刚播放的歌曲从列表中删除,因此它永远不会播放同一首歌曲,直到它循环通过所有其他可能的方式。所以它会从一组歌曲中挑选,当它挑选时让我们说“歌曲 x”,它将从数组中删除“歌曲 x”,以进行下一次随机挑选。只是一个想法......

更新:这是我对该系统的最终实现:http://saradio.tk/new.html

如果您查看源代码并观察控制台,您会看到它从阵列中随机抽取一首歌曲,然后从阵列中删除该歌曲。这样,在播放完所有歌曲之前,它不会重复歌曲。一旦循环到达最后一首歌曲,数组就会恢复到原始状态。

【问题讨论】:

    标签: javascript html html5-audio


    【解决方案1】:

    即使你说你不想拥有大量的数组,只要每首歌曲都有一个前奏列表和一个后奏列表,你就必须以某种方式“了解”它们。你基本上有两个选择:

    1. 建立一个命名约定系统,其中所有的 outros 和 intro 都有相似的文件名和一些后缀
    2. 明确指定所有介绍结尾

    对于 1. ,您的数据结构可能如下所示:

    var intro_suffix = '-intro';
    var outro_suffix = '-outro';
    var extension = '.ogg';
    var songs = [
        {
               base_name: "radio/Barracuda"
            ,  num_intro: 3
            , num_outros: 3
        },
        {
               base_name: "radio/SomeOtherSong"
            ,  num_intro: 3
            , num_outros: 3
        },
    ];
    

    一旦你选择了一首歌曲,你就会得到前奏、主曲和结尾的文件名。例如:

    var song = songs[0];
    var intro_url = song.name
        + intro_suffix
        + (1 + Math.floor(Math.random() * song.num_intros))
        + extension;
    var song_url = song.name + extension;
    var outro_url = song.name
        + outro_suffix
        + (1 + Math.floor(Math.random() * song.num_outros))
        + extension;
    

    对于 2,您的数据结构必须是明确的:

    var songs = [
        {
                 url: "radio/Barracuda.ogg"
            , intros: ["radio/Barracuda-intro1.ogg", "radio/Barracuda-intro2.ogg", "radio/Barracuda-intro3.ogg"]
            , outros: ["radio/Barracuda-outtro1.ogg", "radio/Barracuda-outro2.ogg", "radio/Barracuda-outro3.ogg"]
        },
        {
                 url: "radio/SomeOtherSong.ogg"
            , intros: ["radio/foo.ogg", "radio/bar.ogg", "radio/baz.ogg"]
            , outros: ["radio/meh.ogg", "radio/fuuuuu.ogg", "radio/yo.ogg"]
        },
    ];
    

    然后您将变量导出为:

    var song = songs[0];
    var intro_url = song.intros[Math.floor(Math.random() * song.intros.length)];
    var song_url = song.url;
    var outro_url = song.outros[Math.floor(Math.random() * song.outros.length)];
    

    2. 的一个“优势”是您可以随意命名文件

    【讨论】:

    • 我在输入这个时正在实施想法 #1。我必须做出与几分钟前相同的更改(将 1 添加到 math.floor,因此结果是 x1-x3 而不是 x0-x2。这种方法对我来说效果更好,因为我注意到并非所有歌曲都有 3 个前奏或 outros,并且拥有该系统可确保我可以简单地更改数组中的值,因此“引擎”不会产生无效的源。
    • PS:我还添加了var mid_suffix = '-mid';并更改了var song_url = song.name + mid_suffix + extension;,因此正确的来源song-mid.ogg将用于中间。
    • 很高兴有帮助,请投票或接受对您有用的答案(对不起,那是我无耻和乞求:p)
    • 不错!我看到您在 resetSong 方法中复制歌曲数据。不要那样做。相反,让您的歌曲数据不可变,而是让您的程序在您的歌曲数组的副本上运行。通过在初始化时调用一次 resetSongs 来创建副本。有关信息:要制作数组的(浅)副本,请使用 new_array = old_array.concat();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 2013-03-26
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多