AUD - HTML5 音频播放列表






4.86/5 (6投票s)
使用 HTML5 Audio, JavaScript, Bootstrap, 和 jQuery
引言
过去,在网页中嵌入媒体(视频和音频)的选择不多。 Adobe Flash 可能是唯一的选择。
现在有了 HTML5 的支持,处理 Web 媒体更加愉快。在这个项目中,我将构建一个带有 mp3 轨道播放列表的音频播放器,具有以下基本功能:
- 选择一个音轨并播放、暂停、恢复。
- 前进到下一个,或返回到上一个
- 重复,可以是整个播放列表、单个音轨或随机播放
虽然 HTML 具有对音频的内置支持,但不同的浏览器实现方式不同。有关更多详细信息,您可以查看 w3schools 和 developer.mozilla.org。此外,在这个项目中,我不关心处理旧浏览器的回退。而且 mp3 是我唯一使用的格式。所以,让我们来看看
Chrome 上的 AUD
FireFox 上的 AUD
IE 10 上的 AUD
现在让我们开始吧!
准备工作
由于我们利用了 Bootstrap CSS 框架,因此请下载它并如下所示设置项目。

HTML 结构
应该首先考虑 HTML 结构。它决定了每个其他脚本和样式的运作方式。 JavaScript 和 CSS 可以频繁更改而没有问题。但是,当 HTML 结构发生更改时,它将影响并可能破坏所有内容!
<button type="button" id="playBtn" class="btn btn-primary">Play</button>
<button type="button" id="pauseBtn" class="btn btn-primary">Pause</button>
<button type="button" id="prevBtn" class="btn btn-primary">Prev</button>
<button type="button" id="nextBtn" class="btn btn-primary">Next</button>
<button type="button" id="decreaseVolBtn" class="btn btn-primary">Vol -</button>
<button type="button" id="increaseVolBtn" class="btn btn-primary">Vol +</button>
<form role="form">
<label for="myAudioPlaylist">Select a track from:</label>
<select id="myAudioPlaylist" class="form-control">
<option value="audio/CenturyFox.mp3">Century Fox</option>
<option value="audio/Helicopter.mp3">Helicopter</option>
<option value="audio/UniversalStudios.mp3">Universal Studio</option>
<option value="audio/Horse.mp3">Horse</option>
<option value="audio/Army.mp3">Army</option>
<option value="audio/BabyCry.mp3">Baby Cry</option>
<option value="audio/BraveHeart.mp3">BraveHeart</option>
</select>
<label class="checkbox-inline">
<input id="isRepeat" type="checkbox" value="yesRepeat">
Repeat
</label>
<label class="radio-inline">
<input type="radio" name="repeatOptions" id="optionTrack" value="track" checked>
A track
</label>
<label class="radio-inline">
<input type="radio" name="repeatOptions" id="optionPlaylist" value="playlist">
Playlist
</label>
<label class="radio-inline">
<input type="radio" name="repeatOptions" id="optionRandom" value="random">
Random
</label>
</form>
<!-- / #myDiv -->
ID 为 myAudio 的 HTML Audio 元素是我们的播放器。我们将通过修改 myAudio 的 source 的 src 属性,以编程方式将 mp3 轨道加载到其中
您可以选择通过 ul/ol li 或 a 显示轨道列表。 我为这个项目使用下拉选项列表(ID 为 myAudioPlaylist),因为它更紧凑。
div#myAudioStatus 是一个显示状态信息(暂停、播放、元数据,如持续时间等)的地方。 其他元素通过它们的名称是不言自明的。
JavaScript
HTML 结构设置好后,我们可以通过 CSS 自定义外观。 但这里的所有工作现在都在 script.js 中。
设置 AUD
var AUD = {
player: $("#myAudio")[0],
currentPosition: 0,
totalTracks: 0,
init: function () {
AUD.player.volume = 0.1;
AUD.totalTracks = $('#myAudioPlaylist option').length;
... set initial appropriate values
... listen and handle interested events
},
... more functions
};
这样,我们就有了一个单独的 AUD 对象/变量,并且如果需要,可以避免匿名回调函数。
项目 $("#myAudio")[0](等于 $("#myAudio").get(0))是一个原生 DOM 对象(document.getElementById("myAudio"))。 它们三个都是一样的。 它们不是 jQuery 包装的 DOM 元素对象。
jQuery 对象具有许多有用且易于使用的函数,例如 text()、append()、html() 等,但没有与音频相关的功能、属性和事件。 这就是我们使用 DOM 对象的原因。
响应用户的选择
var AUD = {
player: $("#myAudio")[0],
currentPosition: 0,
totalTracks: 0,
init: function () {
AUD.player.volume = 0.1;
AUD.totalTracks = $('#myAudioPlaylist option').length;
$("#myAudioPlaylist").on("change", function () {
AUD.currentPosition = $("#myAudioPlaylist option:selected").index();
AUD.playTrack();
});
...
},
setTrack: function () {
$('#myAudioPlaylist option').eq(AUD.currentPosition).prop('selected', true);
var trackLink = $("#myAudioPlaylist").val();
$("#myAudio source").attr("src", trackLink);
},
playTrack: function () {
AUD.setTrack();
AUD.player.load();
AUD.player.play();
},
...
};
程序从 init() 函数开始,我们在其中设置合理的起始值,例如音量,或者自动播放/重复与否。 首先想到的是选择音轨(最初由我们选择,然后由用户选择)。 因此,我们处理当用户从提供的列表中选择音轨时产生的 change 事件。
最关键、最重要的是通过 currentPosition 变量来跟踪列表中选定/播放/暂停的音轨的当前位置索引。
大多数代码都是在 init() 中编写的,然后我重构为单独的 setTrack() 和 playTrack() 以降低复杂性,并使其更美观 :)
处理重复选项
var AUD = {
init: function () {
...
AUD.player.addEventListener("ended", AUD.repeat);
...
},
repeat: function () {
if (!$("#isRepeat").prop("checked")) {
//alert("Not repeat");
} else {
// alert("Repeat a single selected track);
if ($("#optionTrack").prop("checked")) {
AUD.playTrack();
} else if ($("#optionPlaylist").prop("checked")) {
// alert("Repeat the whole playlist orderly);
AUD.currentPosition++;
if (AUD.currentPosition >= AUD.totalTracks) {
AUD.currentPosition = 0;
}
AUD.playTrack();
} else {
// alert("Repeat the whole playlist randomly);
AUD.currentPosition = Math.floor(Math.random() * (AUD.totalTracks - 1));
AUD.playTrack();
}
}
},
...
};
我们通过监听 ended 事件(当音轨播放完毕时)来处理重复选项。 然后根据该选项(重复单个音轨、整个播放列表或随机播放),我们可以决定接下来要播放哪个音轨。
处理用户控件
与重复类似且更简单,例如,当用户单击“下一个”按钮时,我们增加 currentPosition++ 并在该位置播放。
其他
在 init() 中还有其他几个函数,例如 toggleRepeatUI() 用于处理重复选项 HTML UI。 listenToAudioEvents() 用于更新状态信息。
完整的 script.js
var AUD = {
player: $("#myAudio")[0],
currentPosition: 0,
totalTracks: 0,
init: function () {
AUD.player.volume = 0.1;
AUD.totalTracks = $('#myAudioPlaylist option').length;
$("#myAudioPlaylist").on("change", function () {
AUD.currentPosition = $("#myAudioPlaylist option:selected").index();
AUD.playTrack();
});
AUD.player.addEventListener("ended", AUD.repeat);
AUD.toggleRepeatUI();
AUD.listenToControllers();
AUD.listenToAudioEvents();
},
toggleRepeatUI: function () {
$("#repeatOptions").hide();
$("#isRepeat").on("change", function () {
if ($("#isRepeat").prop("checked")) {
$("#repeatOptions").show();
} else {
$("#repeatOptions").hide();
}
});
},
listenToControllers: function () {
$("#playBtn").on("click", function () {
// Click Play Button affects only when the player is not playing
if (AUD.player.paused) {
//$("#myAudioPlaylist").trigger("change");
AUD.player.play(); // Play from current paused time
}
});
$("#pauseBtn").on("click", function () {
AUD.player.pause();
});
$("#prevBtn").on("click", function () {
AUD.currentPosition--;
if (AUD.currentPosition < 0) {
AUD.currentPosition = 0;
}
AUD.playTrack();
});
$("#nextBtn").on("click", function () {
AUD.currentPosition++;
if (AUD.currentPosition >= AUD.totalTracks) {
AUD.currentPosition = AUD.totalTracks - 1;
}
AUD.playTrack();
});
$("#decreaseVolBtn").on("click", function () {
AUD.player.volume -= 0.1;
if (AUD.player.volume <= 0) {
AUD.player.volume = 0;
}
});
$("#increaseVolBtn").on("click", function () {
AUD.player.volume += 0.1;
if (AUD.player.volume >= 1) {
AUD.player.volume = 1;
}
});
},
setTrack: function () {
$('#myAudioPlaylist option').eq(AUD.currentPosition).prop('selected', true);
var trackLink = $("#myAudioPlaylist").val();
$("#myAudio source").attr("src", trackLink);
},
playTrack: function () {
AUD.setTrack();
AUD.player.load();
AUD.player.play();
},
repeat: function () {
if (!$("#isRepeat").prop("checked")) {
//alert("Not repeat");
} else {
// alert("Repeat a single selected track);
if ($("#optionTrack").prop("checked")) {
AUD.playTrack();
} else if ($("#optionPlaylist").prop("checked")) {
// alert("Repeat the whole playlist orderly);
AUD.currentPosition++;
if (AUD.currentPosition >= AUD.totalTracks) {
AUD.currentPosition = 0;
}
AUD.playTrack();
} else {
// alert("Repeat the whole playlist randomly);
AUD.currentPosition = Math.floor(Math.random() * (AUD.totalTracks - 1));
AUD.playTrack();
}
}
},
listenToAudioEvents: function () {
AUD.player.addEventListener("loadedmetadata", function () {
var trackName = $("#myAudioPlaylist option:selected").text();
var trackDuration = AUD.player.duration.toFixed(2);
var info = trackName + " (" + trackDuration + "s)";
$("#myAudioStatus p").text("Loaded track: " + info);
});
AUD.player.addEventListener("pause", function () {
var trackName = $("#myAudioPlaylist option:selected").text();
$("#myAudioStatus p").text("Ready: " + trackName);
});
AUD.player.addEventListener("playing", function () {
var trackName = $("#myAudioPlaylist option:selected").text();
$("#myAudioStatus p").text("Now playing: " + trackName);
});
}
};