本文为大家分享一个简易音乐播放器的实现,页面设置参考网易播放器设计,主要使用js+jquery实现前端开发与布局,使用Ajax进行异步请求后端数据。文中展示了详细的代码,供大家参考。项目已发布:xinghuan1998/music-player (github.com)
<body>
<div class="volume-control-panel"> <!--font awesome图标库 音量键-->
<i class="fa fa-volume-up fa-lg"></i>
<div id="volume-bar" class="volume-bar">
<div id="volume-control" class="pro-control" style="bottom:0"></div>
</div>
</div>
<div class="music-detail"><!--font awesome图标库 播放详情页-->
<div class="heder-detail">
<div class="dcol" id="back" style="height:60px;width:50px;line-height: 60px;text-align: center;"><i
class="fa fa-chevron-down fa-lg"></i></div>
<div class="dcol" style="margin: auto;height: 60px;position: absolute;left:50%;transform: translate(-50%);">
<div class="det-title title" style="line-height: 35px;"></div>
<div class="retbutton actor" style="line-height: 25px; text-align: center;"></div>
</div>
</div>
<div class="mid-detail" style="text-align:center;">
<div id="shownimg">
<img class="cover spinner" style="width:100%;height:100%;"
src="https://c-ssl.duitang.com/uploads/item/202005/15/20200515000325_hqpkb.jpg" alt="" \>
</div>
<div class="excircle"></div>
</div>
<div class="bottom-detail">
<div class="pla1" style="text-align:center;">
<span><i class="fa fa-heart-o fa-lg"></i></span>
<span>2</span>
<span>3</span>
<span>4</span>
</div>
<div class="progress">
<div class="pro-bar" id="pro-bar">
<div class="pro-control" id="pro-control"></div>
</div>
</div>
<div class="control">
<div><i class="fa fa-random fa-2x"></i></div>
<div class="backward-button"><i class="fa fa-step-backward fa-2x"></i></div>
<div class="play-button">
<div
style=" border-radius: 50%;border: 2px solid; width:60px;height: 60px;top:44%;left:49%;position: absolute;transform: translate(-50%,-50%);">
</div><i class="fa fa-play fa-2x"></i>
</div>
<div class="forward-button"><i class="fa fa-step-forward fa-2x"></i></div>
<div class="volume-button">
<i class="fa fa-volume-up fa-2x"></i>
</div>
</div>
</div>
</div>
<audio src="" id="main_audio" preload="auto"></audio>
<div class="header">音乐列表
</div>
<div class="body-content">
<div class="music-list">
</div>
</div>
<div class="music-bar"><!-- 页面底部 播放控制按钮-->
<div style="width:50px ;height:60px;float:left;position:relative;padding-left: 0px;margin-top: -10px;">
<img src="https://c-ssl.duitang.com/uploads/item/202005/15/20200515000325_hqpkb.jpg" class="cover spinner"
id="cover">
</div>r
<div class='pmusic-bar' style="width:calc(100% - 130px);float:left;height:60px;padding-left: 20px;">
<span id="title" class="title"></span>
<span style="font-size:10px;color:#cecbcb">- <span id="actor" class="actor"></span></span>
</div>
<div class="play-button" style="width:50px;float:left"><i class="fa fa-play fa-2x"></i></div>
</div>
</body>
// 全局变量
var mainAudio = $('#main_audio');//获取元素
var isPlay = false;//声明一个标记,记录当前播放状态
var isMouseDownOnPlayBar = false;//记录鼠标按下音乐播放按钮状态
var isMouseDownOnVolumeBar = false;//记录鼠标按下音量按钮的状态
var isVolumeBarShow = false;//记录当前音量进度条显示状态
var musicList = [];//设置音乐列表
var playIdxNow = -1;//设置当前正在播放音乐的id
通过ajax先后端发送请求得到歌单列表数据,通过for循环遍历歌单列表,设置每一首歌曲的title,actor,写入到歌单项的HTML模板中,然后通过append函数将歌单项模板添加到div.music-list中。当点击某个音乐时,调用加载音乐播放函数,实现当前点击音乐播放。
function getMusicList() {//获取首页歌单列表
$.ajax({
url: 'http://218.199.4.140:5000/list_music',
success: function (data) {
musicList = data.data;
for (var i = 0; i < musicList.length; i++) {
var actor = musicList[i].actor;
var title = musicList[i].title;
var id = musicList[i].id;
var html = '<div class="item" onclick="loadMusic(' + i + ')">\
<div class="col" style = "width:50px;text-align: center;line-height:43px" >'+ (i + 1) + '</div>\
<div class="col" style="width:calc(100% - 110px);">\
<div class="song">'+ title + '</div>\
<div class="act" style="font-size:80%">'+ actor + '</div>\
</div>\
<div class="col" style="width:50px;line-height:43px"><i class="fa fa-youtube-play fa-lg"></i></div>\
</div></div>';
$('.music-list').append(html);
}
}
})
}
记录当前音乐的索引,通过对应歌曲索引的id访问歌曲播放的请求地址,获取图片,播放地址,通过修改audio的src属性,更改音乐播放的地址,调用音乐播放函数,实现指定音乐的播放。
function loadMusic(i) {//加载指定音乐的index并且播放
playIdxNow = i;
$.ajax({
url: 'http://218.199.4.140:5000/music_info?id=' + musicList[i].id,
success: function (data) {
var cover = data.cover;
var u = data.abc;
var img = data.cover;
$('.cover').attr('src', img);
$('.title').text(data.title);
$('.actor').text(data.actor);
mainAudio.attr('src', u);
musicPlay();
}
})
}
//函数调用
getMusicList();
$(window).keypress(function (e) {
if (e.keyCode != 32) return;
console.log(e)
PlayControl();
});
音乐播放暂停函数
通过audio标签更改音乐的play和pause属性
// 功能函数
function musicPlay() {//音乐播放
mainAudio[0].play();
isPlay = true;
$('.play-button i').removeClass('fa-play').addClass('fa-pause');
}
function musicPause() {//音乐暂停
mainAudio[0].pause();
isPlay = false;
$('.play-button i').removeClass('fa-pause').addClass('fa-play');
}
function musicJumpByPerc(p) {//百分比定位控制音乐进度
mainAudio[0].currentTime = mainAudio[0].duration * p;
}
控制音乐播放事件
通过给播放按钮添加鼠标单击事件,调用控制音乐播放函数。
//控制音乐播放事件
function PlayControl() {
if (isPlay) {
musicPause();
$('.cover').removeClass('spinner');//移除图片旋转动画效果
} else {
musicPlay();
$('.cover').addClass('spinner');
}
};
$('.play-button').click(PlayControl);
切换当前播放音乐事件
通过判断当前播放音乐的索引,调用加载音乐函数,将上一首音乐或下一首音乐的索引传入函数,进行切换播放。
$(".forward-button").click(function () {//播放下一首音乐
if (playIdxNow == musicList.length - 1) {//如果当前音乐的索引等于最后一首歌的索引
loadMusic(0);//下一首歌则为第一首歌
} else {
loadMusic(playIdxNow + 1);//依次将索引加一
}
})
$(".backward-button").click(function () {//播放上一首音乐
if (playIdxNow == 0) {//如果当前音乐的索引等于第一首歌的索引
loadMusic(musicList.length - 1);//上一首歌则为最后一首歌
} else {
loadMusic(playIdxNow - 1);//依次将索引减一
}
})
此控制类包含构造函数,将进度条,进度条控件,进度开始的方向作为参数,分别计算音乐播放进度条(x轴放置在进度条上横向拖动,方向记为left)和音量设置进度条(y轴放置在进度条上纵向拖动,方向记为top)的起点,终点的(x或y)坐标。使用绝对坐标设置进度函数,将事件发生的绝对坐标作为参数,如果该坐标在进度条的开始和结束坐标之间,则修改该坐标的方向属性为该坐标与起点的差(当前坐标在进度条上的长度距离)。使用百分比设置进度函数,将控件占进度条的百分比作为参数,分别用其百分比与进度条长度或高度相乘,设置当前进度的距离长度。获取进度函数,通过控件当前的距离比上进度条的距离得出当前控件进度百分比。后面将进度百分比传入音乐播放进度函数中,即可实现音乐播放进度与控件进度同步的效果。
音乐进度条和音量进度条分别调用此函数,得到两者控件的进度百分比。
//进度条控制类
class ProgressBar {
constructor(bar, dot, direction) {
this.bar = bar;
this.dot = dot;
this.direction = direction;
if (direction == 'left') {
this.start = bar.offset().left;//计算进度条开始坐标x
this.end = this.start + bar.width() - 5;//结束x坐标
}
else {
this.start = bar.offset().top;//计算音量控制小圆点的开始坐标y
this.end = this.start + bar.height() - 5;//结束坐标y
}
}
setPosByEvent(x) {//使用绝对坐标X设置进度
if (x <= this.end && x >= this.start) {
this.dot.css(this.direction, x - this.start + 'px');//进度条当前进度(根据小圆点x坐标计算)
}
}
setPosByPerc(p) {//使用百分比设置进度
if (this.direction == 'left')
var x = p * this.bar.width();
else
var x = p * this.bar.height();
this.dot.css(this.direction, x + 'px');
}
getPosByPerc() {//使用百分比获取进度
return +this.dot.css(this.direction).replace('px', '') / (this.end - this.start);//获取控制小圆点的属性,并用空字符代替px进行百分比计算
}
}
var musicBar = new ProgressBar($('#pro-bar'), $('#pro-control'), 'left');
var volumeBar = new ProgressBar($('#volume-bar'), $('#volume-control'), 'top');
对鼠标进行监听,设置鼠标移动事件,记录鼠标当前(按下,弹起)的状态,鼠标按下时修改默认flag值为true,当鼠标弹起时,仍为false。在鼠标移动事件下对鼠标状态做一个判断,如果为按下时,则执行上文的(进度条拖动函数),否则不执行。
//PC端添加Mouse事件
$('#pro-control').on('mousedown', function () {//进度条控制圈按下事件
isMouseDownOnPlayBar = true;
});
$('#volume-control').on('mousedown', function () {//进度条控制圈按下事件
isMouseDownOnVolumeBar = true;//记录鼠标按下状态
console.log('mousedown')
});
$(document).on('mousemove', function (event) {//鼠标移动函数,在鼠标按下状态改变进度条的控件位置属性
if (isMouseDownOnPlayBar) {//如果鼠标按下,则执行绝对坐标定位函数,确定控件在进度条上距离起点的长度距离
musicBar.setPosByEvent(event.pageX);
var p = musicBar.getPosByPerc();//获取音乐进度条的百分比
musicJumpByPerc(p);//通过音乐进度条百分比设置音乐播放进度
}
if (isMouseDownOnVolumeBar) {
volumeBar.setPosByEvent(event.pageY);//如果鼠标按下,则执行绝对坐标定位函数,确定控件在音量条上距离起点的高度距离
var p = volumeBar.getPosByPerc();//获取音量控件在进度条的百分比
mainAudio[0].volume = 1 - p;//通过音量进度条百分比设置音量的大小
}
});
$(document).on('mouseup', function () {
isMouseDownOnPlayBar = false;
isMouseDownOnVolumeBar = false;
});
该函数等同于音乐播放进度函数,流程同上。
$('.volume-button').click(function () {//音量进度条显示隐藏事件
if (isVolumeBarShow) {
$('.volume-control-panel').hide();//音量控制条隐藏
isVolumeBarShow = false;
} else {
$('.volume-control-panel').show();//将音量进度条显示
volumeBar = new ProgressBar($('#volume-bar'), $('#volume-control'), 'top');//调用进程函数设置音量的大小,控件跟随鼠标移动
isVolumeBarShow = true;//更改隐藏状态
}
}).blur(function () {//鼠标失去焦点 音量控制隐藏
$('.volume-control-panel').hide();
isVolumeBarShow = false;
});