65.9K
CodeProject 正在变化。 阅读更多。
Home

AUD - HTML5 音频播放列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (6投票s)

2015年9月4日

CPOL

3分钟阅读

viewsIcon

25392

downloadIcon

888

使用 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 元素是我们的播放器。我们将通过修改 myAudiosourcesrc 属性,以编程方式将 mp3 轨道加载到其中

	
    

您可以选择通过 ul/ol lia 显示轨道列表。 我为这个项目使用下拉选项列表(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);
	});
    }
};

END

© . All rights reserved.