HTML+js 简易音乐播放器:原理、代码与开发环境综述
概述
为了工作需要和学习目标,笔者目前正在学习HTML多媒体相关内容,其中的重点之一就是音乐播放器。但是翻看大部分网站提供的源码和教程,并没有比较完整的HTML音乐播放器教学。结合自己这几天的学习和实践,总结了一个比较简单的HTML音乐播放器集成代码。这里就将播放器的内容和用途向大家进行演示和讲解,希望能帮助到更多愿意学习Web编程的人和业内人士。
HTML音频介绍及开发环境1.音频控制
到目前为止,网页上播放音频还没有标准。如今,大多数音频都是通过插件播放的(例如 Flash,现在已经过时了)。然而,并非所有浏览器都拥有相同的插件。HTML5 规定了一种通过 audio 元素包含音频的标准方式,它可以播放声音文件或音频流。标准写法如下:
<audio>audio>
1.音频控件基本属性 2.音频控件基本响应事件 2.开发环境代码及原理介绍
本文提到的音乐播放器是一个单独的页面,没有css和js文件。所有功能都在一个HTML页面中实现,没有任何多余的东西。下面的代码是逐渐完善的一段代码,而不是整体。直接从本文中复制使用作者的代码时请仔细阅读,不要随意复制粘贴。(如果你只是CV程序员,那就麻烦了,呵呵,你是国企程序员,无视我说的话就好……)
1.添加播放器控件及相应资源
新建一个 HTML 页面,在 body 中添加一个音频控件,暂时不要写它自己的属性:
...
<div>
<audio>audio>
div>
...
通常,在 中,音频控件如下所示:
资源可以随意添加,比如我们现在我的项目根目录 src/ 里有三首音乐
2. 创建播放列表
制作一个单行表格。此表格应像播放列表一样可滚动,因此应将表格加载到具有固定高度的 div 中。首先,添加一个表格:
<h2>播放列表h2>
<div class="musicList">
<table id="myTable">table>
div>
<button>上一首button>
<button>下一首button>
<button id="music_rand">随机播放button>
<input type="checkbox" id="loop_ck">单曲循环button>
给表格添加一点样式,这里就不深入解释每个样式代表什么了,稍微懂点CSS3的人都能看懂。不要介意里面的一些稀奇古怪的样式,不加的话你会后悔的,用浏览器调试工具自己看看效果吧。这一段可以写在head标签下的style标签里:
<style>
.musicList{width: 300px; height: 10em;border: 1px solid black;table-layout: fixed;}
#myTable{width: 100%;border: 1px solid black;border-collapse: collapse;table-layout: fixed;overflow-y: auto;}
/* 为什么把myTable的高度超出样式设置为自动,后文会讲到 */
td{text-align: left;font-weight: 700; border: 1px solid black;}
th{text-align: left;writing-mode: vertical-rl;transform: rotate(180deg);padding: 0.25em;vertical-align: text-bottom;border: 1px solid black}
style>
该表具体样式如下:
3. 播放列表动态加载
废话不多说,就ajax,最好有(再次声明,是免费的,自己去下载吧,不要深入学习,否则跟1949年参军没两样)。你问我为什么要动态加载?亲爱的读者,你醒了吗?播放列表当然会更新,你最好自己写一个文件上传相关的(不会的话直接搜一下,上传文件很方便,甚至不用等框架。我一直力求教给大家最简单的东西,所以本文就不涉及文件上传了,毕竟没必要,使用某个播放器的用户也不可能自己上传,算是在线更新播放器后台数据的一个尝试,比如网易云等很多平台)。
我使用JSON文件来存储音乐资源列表,里面是一个数组,可以通过上传文件来更新,读者最好自己准备一个。
.json:
["歌唱动荡的青春-Lube", "guitar", "lite"]
然后添加ajax请求json,如下,写在页面的标签体中:
<script>
var files = [];
var audio = document.getElementById("audio1");
$.ajax({
url: "./json/musicName.json",
type: "get",
success: function (res) {
files = res;
let ls = res;
// 动态添加音乐资源于audio控件,这条语句↓的作用是设置默认播放的音乐,我选择的是json中的首位
$("#audio1").prop("src", "src/audio/" + res[0] + ".mp3");
for (let i = 0; i < res.length; i++) {
/* 动态生成表格内容,实际上我不推荐这样做,乐曲数量太多会给网页带来加载负担,最好是分次数动态请求,笔者这里是因为只有
三个就稍微写简单一点,笔者会写分次请求,有需要时会教给各位读者。 */
$("#myTable").append('+ i + '" value="' + ls[i]
+ '" οnclick="musicPlaying(`ml' + i + '`)"> ');
}
}
});
script>
很多人会对这段代码产生疑惑:第一,为什么会有一个全局变量来获取请求返回的结果res?后面还会用到,需要设计的东西很多。为了保证这个数组不会消失,作者选择以全局变量的形式保存。如果读者知道怎么用,作者还是不忘初心,只教最简单的方式,更方便优化代码。第二,返回值res可以直接使用,为什么要多写一层内部变量ls来携带呢?慎重一点,毕竟这不是公共的方法,而是内置的请求成功的方法函数。最好用内部变量来携带ajax请求成功的返回值,因为可能涉及到修改res,直接修改res会造成一些不必要的影响或者错误。尽量修改一个携带变量,而不是返回值本身。
可以看到,请求成功函数以只读的方式将一个输入框加载到单行表中。这样做的目的是为了让用户能够点击这个输入框来切换音乐。我已经提前建好了一个函数调用。为此,我们需要给这个输入框分配一个类,并修改它的样式:
<style>
...
.ML{width: 95.5%;padding-left: 0.5em;outline: none;cursor: pointer}
/* 光标指针过于难看,因此用cursor定义了手指类型,也可以附加url使用你们的鼠标图示 */
style>
当ajax请求完成后我们就可以看到表格的变化了,此时由于音乐资源已经动态的成为了audio标签里的属性,因此也可以进行操作了:
4.功能 (1)点击播放列表可以切换歌曲,以及更改正在播放歌曲栏目的样式。
这是音乐播放列表的基本功能之一,内置函数开始生效,核心原理就是用户点击这一列之后,系统获取输入框里的值,把这个值转换成适合音频控件的 src 属性的完整 URL,加载这段音乐,然后播放。不光音乐,视频播放器也可以用我的逻辑。你去过哔哩哔哩(不是广告不是广告不是广告)吗?你也看过哔哩哔哩的合集视频吗?这个播放列表的思维逻辑和那个差不多……
B站UP主阿卡大文先生的精选视频播放列表:
以上代码:
function musicPlaying(id) {
audio.pause(); // 暂停
$("#audio1").prop("src", ""); // 置空资源,强行停止播放,算是一个保险
/* 点击后用新的value填充 */
let val = $("#" + id).val();
$("#audio1").prop("src", "src/audio/" + val + ".mp3");
audio.play(); // 播放
}
function Playing() {
let name = decodeURI($("#audio1").prop("src").replace("http://localhost:8443/Blog/src/audio/", "").replace(".mp3", ""));
$("input[id*=ml]").each(function () {
let val = $(this).val();
let now = null;
// console.log(name);
if (val.indexOf("正在播放") !== -1) {
now = val.replace("正在播放 —— ", "");
if (now === name) {
$(this).css({"background-color": "black", "color": "white"});
$(this).val(val);
} else {
$(this).css({"background-color": "white", "color": "black"});
if (val.indexOf("正在播放 —— ") !== -1) {
$(this).val(now);
}
}
} else {
if (val === name) {
$(this).css({"background-color": "black", "color": "white"});
$(this).val("正在播放 —— " + val);
} else {
$(this).css({"background-color": "white", "color": "black"});
}
}
});
}
这个函数怎么调用呢?如果直接调用的话,有几率和ajax请求冲突。因此我在ajax请求完成后给页面添加了一个监听器,用来监听上面提到的play方法。事件监听方法我就不多说了,读者可以自行搜索:
$.ajax({
// 略
complete: function () {
audio.addEventListener("play", Playing);
}
});
我先解释一下为什么现在会出现中间变量,因为播放列表中对应正在播放的音乐的列的值发生了变化,所以我们在做判断之前需要去掉前缀,不然这个函数的判断条件会导致函数内容间隔执行,并不是我们想要的效果。虽然很简单,但我觉得这部分的思路已经传达出来了,下面是加上这部分之后的播放效果:
(2)上一首、下一首、顺序播放
(此段代码仅供参考)
就跟网易云音乐播放列表中的上一首下一首一样,不过我们用更简单的方法。首先顺序播放这个功能不难,之前提到过全局变量files的问题,现在就可以用了。作者的逻辑是监听播放结束时间,用一个索引变量index记录当前歌曲在files中的位置,播放完成后自动切换到下一首(index++)。如果已经是列表末尾,直接将index置0即可。代码如下:
function next() {
if (index === files.length - 1) {
index = 0;
} else {
index++;
}
$("#audio1").prop("src", "src/audio/" + files[index] + ".mp3");
audio1.play();
}
为 ajax 方法添加结束事件监听器:
$.ajax({
// 略
complete: function () {
audio.addEventListener("play", Playing);
audio.addEventListener("ended", next, false);
}
});
这个方法为什么有个false呢?这是事件监听器的第三个参数,它的主要作用是区分事件冒泡(false,从内向外,直接到达触发事件的控件,然后上升到整个HTML)和事件捕获(true,从外向内,从HTML一步步上升,最后找到触发事件的位置,也就是控件)。用false直接冒泡会省时很多mp3音乐播放器,虽然可能只快了零点几毫秒,但已经足够了。
同时这个方法还可以用于手动播放下一曲,所以我们把它绑定到“Next”按钮上。笔者这里直接用了标签体属性。你也可以使用 Vue 框架。我把这三个常用框架的表示方式写下来,防止有些人偷懒,连改都不改就想直接用 CV。后面就不细说了,只说最简单的一种:
HTML标签体的基本写法:
<button onclick="next();">下一首button>
js中各种写法(部分示例):
// 记得给button添加id,我这里不赘述,直接写一个id
$("#next").click(()=>{next();});
$("input[id=next]").click(function(){next();});
document.getElementById("next").onclick = function(){next();};
如果你使用Vue,那么可以这样写:
(html 内)
<button @click="next();">下一首button>
或者
<button v-on="{click:next}">下一首button>
(在 js 中)
// 前略
methods:{
next(){
// 内容就是刚才next函数的内容
},
}
以上就是下一曲和顺序播放的函数设置及实例化绑定,想要操作上一曲只需要切换next函数的逻辑,获取当前索引位置,然后顺序减1,如果已经减到0就返回到最后,直接上代码:
function pre() {
if (index === 0) {
index = files.length - 1;
} else {
index--;
}
$("#audio1").prop("src", "src/audio/" + files[index] + ".mp3");
audio1.play();
}
然后将此方法绑定到上一个控件上:
<button onclick="pre();">上一首button>
(3)单曲循环
所谓单曲循环,其实就是给音频控件动态添加 loop 属性,甚至不需要写 loop="loop",就像输入的 and 一样,浏览器的自定义功能会自动补全属性值。逻辑就是每次点击,如果勾选了就添加这个属性开始循环,否则丢弃这个属性退出循环。值得注意的是,开启循环后自动切换歌曲功能会失效,因为 loop 属性的核心其实相当于强行拖动进度条到开头,而不是重新开始播放歌曲。代码如下:
function musicLoop() {
if ($("#loop_ck").prop("checked")) {
$("#audio1").attr("loop", true);
} else {
$("#audio1").removeAttr("loop");
}
}
同时将该函数绑定到单循环上:
<input type="checkbox" id="loop_ck" onclick="musicLoop();">单曲循环button>
(4)随机播放
逻辑就是调用生成随机数的函数,生成一个0~数组长度-1(最后一个索引)范围内的随机数,以此为索引,获取资源名并改变音频控件的资源值。这里为了方便(控件id是预先设定好的),我直接绑定了事件函数。代码如下:
// 生成随机数的函数 ↓
function randomNum(minNum, maxNum) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1, 10);
break;
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
break;
default:
return 0;
break;
}
}
$("#music_rand").click(function () {
index = randomNum(0, files.length - 1);
$("#audio1").prop("src", "src/audio/" + files[index] + ".mp3");
audio1.play();
});
(5)滚动播放列表
前面设置了列表自动改变高度的样式,这里可以用到。首先要预设播放列表单页的最大显示量,笔者已经设置了容器高度为10em,所以限制表格最多显示六行,程序的逻辑原理就是表格超过6行后才滚动。如有需要,读者可以放出笔者代码的注释部分,可以让表格容器随着表格高度实时改变宽度。为了保证代码不失效,还必须限制在ajax请求完成后执行,如下:
function makeTableScroll() {
var maxRows = 6;
var table = document.getElementById('myTable');
var wrapper = table.parentNode;
var rowsInTable = table.rows.length;
var height = 0;
if (rowsInTable > maxRows) {
for (var i = 0; i < maxRows; i++) {
height += table.rows[i].clientHeight;
}
// wrapper.style.height = height + "px";
}
}
...
...
...
$.ajax({
// 略
complete: function () {
makeTableScroll() ;
audio.addEventListener("play", Playing);
audio.addEventListener("ended", next, false);
}
});
之后我们得到一个可滚动的播放列表(不要担心内容,我添加了重复的名称以便进行测试):
至于其他功能,比如样式、变化等,大家可以自行添加,本文就不再赘述。
结论
以上是我能想到的最简单的音乐播放器,重点讲解了如何实现类似网易云音乐等其他主流音乐播放器的播放列表效果,非100%原创,允许转载,欢迎大家使用。
百度百科词条·HTML5音频
CSDN博客:使用HTML5创建音乐播放列表
阴阳师4月22日更新内容:帝释天上线技能调整,红莲华冕活动来袭[多图],阴阳师4月22日更新的内容有哪些?版本更新
2024-06-04四川电视台经济频道如何培养孩子的学习习惯与方法直播在哪看?直播视频回放地址[多图],2021四川电视台经济频
2024-06-04湖北电视台生活频道如何培养孩子的学习兴趣直播回放在哪看?直播视频回放地址入口[多图],湖北电视台生活频道
2024-06-04