在线音乐播放器项目02

目前进度

1.初步构建了上方导航栏,以及实现了搜索联想功能,如下图所示。

image-20241001003911303

通过看之前的javaweb项目重新复习一遍了搜索联想功能的实现。

2.设置了分页查询功能。

这次的分页查询并没有像之前的web项目一样,通过每次点击相应的图标而发送请求到servlet中进行交互,而是通过vue的帮助,实现了一次获取数据即可实现分页查询功能,很是方便。

3.重新设计了音乐播放器的显示

由于html自带的audio标签的样式不是很好看,所以查找了各种信息,最终在B站找到了一个很不错的视频,通过该视频的学习,在另一个网页初步构建了新的音乐播放器,后续会完成该播放器其余内容后将其移植到当前的音乐播放器项目里。如下图所示。

image-20241001004512225

学习视频链接【HTML+CSS3+JS实现音乐播放器项目】https://www.bilibili.com/video/BV1tj411N7SH?vd_source=ad14811b0629f215912c584fbe9d9875这个视频可以说收获相当多,让我对网页布局有了新的认识和更好的写代码逻辑与规范。

收获

我先把分页查询功能完善后,晚点再写吧。

2024/10/7

一、自定义音乐播放器交互功能实现流程:

1.先通过ajax将音乐数据从数据库中读取出来存入变量musiclist中。

1
2
3
4
5
6
7
8
9
10
11
//1.加载音乐列表信息
$.ajax({
type: "GET",
url: "http://localhost:8080/mvn01/test",
dataType: "json",
success: function(data){
musiclist = data;
render(musiclist[currentIndex]);
renderMusicList(data);
}
});

2.在点击播放按钮后,除了要播放当前音乐外,还需要将页面背景和音乐信息卡片的内容进行更改,由于该功能具有复用性,所以需要新建加载函数来实现相应的内容更改。

1
2
3
4
5
6
7
8
9
10
11
12
//根据信息,设置页面对应的标签内容
function render(data){
$(".name").text(data.name);
$(".singer").text(data.singer);
$(".time").text(data.time);
$(".cover img").attr("src", data.cover);
$("audio").attr("src", data.audio_url);
$(".mask_bg").css({
background: `url("${data.cover}") no-repeat center center`,
"background-size" : "cover"
})
}
  1. 给播放按钮添加点击事件时需要考虑当前的播放状态,一开始的想法是判断当前的播放图标来更改音乐的播放与暂停,但在实现音乐的上一首和下一首的功能时,若当前是播放,会出现下一首显示图标暂停,下下一首显示播放,而实际上都是在播放的问题,因为audio在更换音乐源时,图标没有继续更改。所以为了方便,发现了可以用audio的paused属性$("audio").get(0).paused 可以告知音乐是否暂停,若暂停,则返回true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//给播放按钮添加点击事件
$("#playBtn").on('click', function(){
//1.判断当前播放状态
if($("audio").get(0).paused){
//修改播放状态
isplay = true;
//0.改变播放图标状态
$(this).attr("src", "image/icon/暂停.png");
//1.音乐播放

$("audio").get(0).play();
//2.动态显示卡片信息
$(".player-info").animate({
top: '-100%',
opacity: 1
},
"slow");
//3.封面旋转起来
$(".cover").css("animation-play-state", "running");

}else{
//修改播放状态
isplay = false;
//0.改变播放图标状态
$(this).attr("src", "image/icon/播放.png");
//1.音乐暂停播放
$("audio").get(0).pause();
//2.动态显示卡片信息
$(".player-info").animate({
top: '0%',
opacity: 0
},
"slow");
//3.封面旋转暂停
$(".cover").css("animation-play-state", "paused");
}
//2.播放后重新渲染音乐列表
renderMusicList(musiclist);

4.实现上一首和下一首播放时,要注意变量的范围,不能一直加也不能一直减,所以要对音乐索引的临界点进行判定。此外再调用render函数和触发播放按钮的点击事件来进行音乐的播放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//给上一首按钮绑定事件
$("#prevBtn").on('click', function(){
//1.当前播放音乐索引减一
if(currentIndex > 0){
currentIndex --;
}else{
//若是第一首,则跳转至最后一首
currentIndex = musiclist.length - 1;
}

//2.调用render函数 重新渲染歌曲信息
render(musiclist[currentIndex]);
//3.让音乐播放 触发播放按钮事件
$("#playBtn").trigger("click")
});
//给下一首按钮绑定事件
$("#nextBtn").on("click", function(){
//1.当前播放音乐索引加一
if(currentIndex < musiclist.length - 1){
currentIndex ++;
}else{
//若是最后一首,则跳转至第一首
currentIndex = 0;
}

//2.调用render函数 重新渲染歌曲信息
render(musiclist[currentIndex]);
//3.让音乐播放 触发播放按钮事件
$("#playBtn").trigger("click");
})

5.实现音乐播放列表的显示时,我们需要动态的实时更新音乐列表,所以要创建一个可复用的函数renderMusicList()以便播放状态信息的实时更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//根据音乐列表创建li
function renderMusicList(list){
//先清空列表
$(".music-list").empty();
$.each(list, function(index, item){
var $li = $(`
<li class="${currentIndex == index ? "playing":""}">
<span>${index+1 < 10? "0"+(index +1) : index + 1}.${item.name}-${item.singer}</span>
<span data-index="${index}"><img class="play-circle" src="${currentIndex == index && !$("audio").get(0).paused ? 'image/icon/暂停.png': 'image/icon/播放.png'}"></span>
</li>
`);
//重新加载列表
$('.music-list').append($li);
})
}

该函数所用的地方有 列表图标的点击事件、音乐列表中的播放按钮点击事件、主界面播放按钮的点击事件。主界面播放按钮的点击事件用到的地方多,涵盖了音乐列表信息更新所要关联的地方,方便实现动态更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//给音乐列表绑定事件
$("#openModal").on('click', function(){
$(".modal").css({
"display": 'block'
});
renderMusicList(musiclist);
});
//给音乐列表按钮添加点击事件
$(".music-list").on('click', 'li span', function(){
//修改当前音乐索引
if(currentIndex == $(this).attr('data-index')){

}
else{
currentIndex = $(this).attr("data-index");
//先设置标签内容
render(musiclist[currentIndex]);
}
//再触发播放功能
$("#playBtn").trigger("click");

});

6.顺序播放、随机播放和单曲循环的实现。该功能应该位于音乐播放结束时实现,所以要监听audio的ended状态,由于在添加移除监听事件需要指定移除的函数,否则无效,所以不能用匿名函数来添加点击事件,所以只能创建相应的函数来进行监听事件的更改。每次点击播放设置图标时,会移除监听audio的上一个事件,再添加当前事件。目前还未实现在随机播放状态下点击下一首时实现随机播放的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//给音乐播放设置按钮绑定点击事件
$("#setBtn").on("click", function(){
if($(this).attr("play-model") == 1){
$(this).attr("play-model", 2);
$(this).attr("src", "image/icon/随机播放.png");
RadPlay();
}else if($(this).attr("play-model") == 2){
$(this).attr("play-model", 3);
$(this).attr("src", "image/icon/单曲循环.png");
CirPlay();

}else{
$(this).attr("play-model", 1);
$(this).attr("src", "image/icon/顺序播放.png");
$("audio").get(0).removeEventListener("ended", null);
SeqPlay();
}
})
//顺序播放
function SeqPlay(){
$("audio").get(0).removeEventListener("ended", cirplay);
$("audio").get(0).addEventListener("ended", seqplay)
}
function seqplay(){
currentIndex = currentIndex > musiclist.length - 1 ? 0 : currentIndex + 1;
render(musiclist[currentIndex]);
//顺序播放直接出发下一首事件
$("#playBtn").trigger("click");
}
//随机播放
function RadPlay(){
$("audio").get(0).removeEventListener("ended", seqplay);
$("audio").get(0).addEventListener("ended", radplay);
}
function radplay(){
//随机获取一个音乐索引
var origin = currentIndex;
while(origin == currentIndex)
currentIndex = parseInt(Math.random()*100) % musiclist.length;
//重新渲染音乐信息
render(musiclist[currentIndex]);
//触发点击事件
$("#playBtn").trigger("click");
}

function CirPlay(){
$("audio").get(0).removeEventListener("ended", radplay);
$("audio").get(0).addEventListener("ended", cirplay);
}
function cirplay(){
$("#playBtn").trigger("click");
}

吐槽

我觉得网页最难懂的就是css了,样式太多了,设计页面好麻烦。我对前端内容不是很熟悉,所以在调整css样式方面可以说是相当难受,就是调整不到自己想要的显示效果,因为很多css属性我都是一点不清楚,问ai也是牛头不对马脚。