08.17 今天接着完成音乐播放器的功能
接着上一篇【小河今学 | JavaScript + JQuery】音乐播放器2-功能实现,今天主要实现音乐播放器的歌词轮播和进度条跳转功能实现。
一、歌词轮播
首先我们需要获得歌词,这里我们要用到JQ里的方法 $.get()
,这个方法是通过远程HTTP,GET请求载入信息,以此获取到我们要的歌词内容,具体代码如下:
$.get(url).then(function(data) {
// $.get()方法通过远程HTTP GET请求载入信息
// then()方法是异步执行,就是当then()前的方法执行完后,再执行then内部的程序。
console.log(data)
}
以上代码需要拿到的url即当前播放歌曲的lrc,因此我们封装一个方法,同时在play()方法里调用这个方法,即:
function getSongText(url) {
$.get(url).then(function(data) {
// $.get()方法通过远程HTTP GET请求载入信息
// then()方法是异步执行,就是当then()前的方法执行完后,再执行then内部的程序。
console.log(data)
}
// 在play()中调用
function play(index){
// 改变audio的src
player.src = songs[index].url;
player.play();
// 点击别的歌曲时,若当前播放键为(三角形),则换成(直立等于)
if($('.pp').hasClass('play')){
// console.log(11)
$('.pp').removeClass('play')
$('.pp').addClass('pause');
}
// 获取当前歌曲的歌词
getSongText(songs[index].lrc)
}
于是我们可以得到控制台输出为:
接着我们需要将每一句歌词都拆分出来为一个字符串,这里用到正则表达式来作为判断(具体的符号意思都写在注释里),然后再将每一句歌词中的时间和歌词分开来,最后我们将时间转换成以秒为单位的数字,方便用来与audio的currenTime作比较
// 提取每句歌词,用正则表达式来匹配
var reg = /\[(\d{2}):(\d{2}).(\d{2})\].*/g;
// \d表示匹配数字,.表示匹配除换行符外的任何单个字符,*表示匹配前面的子表达式零次或多次,/g表示返回多个匹配结果
var songText = data.match(reg);
// 切割出时间
for(var i = 0; i < songText.length; i++){
// 将时间与文字分隔开
var singleTxt = songText[i].substr(1).split(']');
// substr(start) 方法可在字符串中抽取从 start 下标开始的指定数目的字符。
// split(separator) 方法用于把一个字符串分割成字符串数组,从该参数指定的地方分割。
// 所以得到singleTXT[0]为时间,singleTXT[1]为文字
// 接着将时间转换成以秒为单位的数字
var timeNum = singleTxt[0];
var m = timeNum[0] = 0 ? timeNum[1] : timeNum.substr(0,2);
var s = timeNum[3] = 0 ? timeNum[4] : timeNum.substr(3,2);
var hs = timeNum[6] = 0 ? timeNum[7] : timeNum.substr(6,2);
var finalTime = parseInt(m * 60) + parseInt(s) + parseFloat(hs / 100);
console.log(finalTime);
}
可以看到此时控制台就会输出每句歌词的具体时间(以秒为单位)
接着需要同步歌词我们就要用到一个计时器,因此这里在全局中需要设定一个新的变量歌词计时器,同时封装一个方法,将我们分好的每一句时间和歌词传进这个方法,在通过这个计时器来渲染到页面上。这里我们就需要将每一句的时间和歌词用一个数组来装起来,方便我们的使用。
// 切割歌词
function getSongText(url) {
// 设定一个数组来存放时间和歌词
var arr = [];
$.get(url).then(function(data) {
// $.get()方法通过远程HTTP GET请求载入信息
// then()方法是异步执行,就是当then()前的方法执行完后,再执行then内部的程序。
// console.log(data)
// 提取每句歌词,用正则表达式来匹配
var reg = /\[(\d{2}):(\d{2}).(\d{2})\].*/g;
// \d表示匹配数字,.表示匹配除换行符外的任何单个字符,*表示匹配前面的子表达式零次或多次,/g表示返回多个匹配结果
var songText = data.match(reg);
// 切割出时间
for(var i = 0; i < songText.length; i++){
// 将时间与文字分隔开
var singleTxt = songText[i].substr(1).split(']');
// substr(start) 方法可在字符串中抽取从 start 下标开始的指定数目的字符。
// split(separator) 方法用于把一个字符串分割成字符串数组,从该参数指定的地方分割。
// 所以得到singleTXT[0]为时间,singleTXT[1]为文字
// 接着将时间转换成以秒为单位的数字
var timeNum = singleTxt[0];
var m = timeNum[0] = 0 ? timeNum[1] : timeNum.substr(0,2);
var s = timeNum[3] = 0 ? timeNum[4] : timeNum.substr(3,2);
var hs = timeNum[6] = 0 ? timeNum[7] : timeNum.substr(6,2);
var finalTime = parseInt(m * 60) + parseInt(s) + parseFloat(hs / 100);
// console.log(finalTime);
arr.push({
time: finalTime,
text: singleTxt[1]
})
}
setSongText(arr);
})
}
// 歌词同步切换
function setSongText(arr) {
// 回收内存
clearInterval(songTime);
songTime = setInterval(() => {
$.each(arr,function(idx,item){
var curTime = item.time - player.currentTime - 0.5; //这里调一个0.5秒是因为我发现歌词有延迟,所以进行的一个调整,可以根据实际情况进行调整
if(curTime < 0){
$('.sing-words').html(item.text)
}
})
}, 500);
}
接着就可以在页面上看见实现的歌词轮播效果了
二、进度条跳转功能
要实现这个功能,首先我们要获取到我们鼠标在进度条上点击的位置,从而用这个位置除以进度条的宽度在乘上总时长来跳转到我们点击的这个位置的时间。
因此我们先获取鼠标在页面上的位置,这里我们封装一个方法
// 鼠标点击位置
function getMousePosition(e){
var e = e || window.event;
var x = e.pageX;
var y = e.pageY;
return {'left':x,'top':y}
}
获取到鼠标点击位置后,我们要在进度条上绑定一个点击方法,在这个方法里调用我们获取鼠标点击位置的方法从而通过计算获取到我们点击的这个位置对应的时间。
$('.progress').click(function(){
// 获取当前鼠标点击的位置
// console.log(getMousePosition().left)
// console.log($('.progress').offset())
var long = (getMousePosition().left) - ($('.progress').offset().left);
// console.log(long)
// 将当前点击的长度重新给p标签
$('.progress p').width(long);
// 获得当前点击长度的时间
var nowtime = (long/$('.progress').width()) * allTime;
}
获取到点击对应的时间后,我们应当将当前的时间清除,把点击获得的时间,重新付给audio的currentTime。由于在之前的代码中,我们将赋给audio.currentTime写在了计时器中,没有办法自行调用,因此这里要将这一部分拿出来重新封装成一个方法。
// 重置时间和进度条
function setCurTime(nowtime,sking){
// 判断是否跳跃点击进度条
if(sking){
// 修改当前时间
player.currentTime = nowtime;
}
ct = fixTime(player.currentTime);
$('.curtime').html(ct);
// 进度条跟着前进,首先获得当前进度长度
allTime = parseInt(player.duration);
curTime = parseInt(player.currentTime);
var proWidth = (curTime / allTime) * $('.progress').width();
$('.progress p').width(proWidth)
// console.log(proWidth)
// 测试后发现播放完后进度条没有满,因此进行一个判断语句
proWidth = proWidth < $('.progress').width() ? proWidth : $('.progress').width();
// 进度条点击跳转
$('.progress').click(function(){
// 获取当前鼠标点击的位置
// console.log(getMousePosition().left)
// console.log($('.progress').offset())
var long = (getMousePosition().left) - ($('.progress').offset().left);
// console.log(long)
// 将当前点击的长度重新给p标签
$('.progress p').width(long);
// 获得当前点击长度的时间
var nowtime = (long/$('.progress').width()) * allTime;
// 清除当前的时间
clearInterval(timer);
setCurTime(nowtime,true);
})
}
// 显示实时进度
player.addEventListener('playing',function(){
// 这里需要用到计数器,一秒钟刷一次,这样才能达到实时的效果
timer = setInterval(() => {
setCurTime(player.currentTime);
}, 1000);
})
以上就是全部内容,还有音乐播放和循环留到明天继续。