Lily_music 網頁音樂播放器 -可搜尋(附歌詞聯動播放效果解說)
部落格地址:https://ainyi.com/#/59
寫在前面
這是我今年(2018)年初的小專案,當時也是手賤,不想用別的播放器,想著做一個自己的網頁播放器,有個歌曲列表、可關鍵詞搜尋、歌詞滾動播放的效果,於是乎,就做了這一個 Lily_music
當時的感慨
有好幾天沒有發表部落格了,這也是因為一直開發音樂和完善我的部落格專案,好不容易抽出時間總結一下這幾天所做的東西,還這麼多課,實則匆忙
今天難得逃了一次課,就趁這時間,該寫寫就寫寫吧~~
進入正題:Lily_music
本次開發,參照本人之前所做的 樂詩部落格(文末會說到)的相關播放控制等功能,繼續優化的結果
前端模仿qq音樂介面,然後在此之上進行修改的介面,並使用了一點 es6 的語法
話說個人挺喜歡qq音樂介面的,簡潔,當然也少不了背景模糊外掛以及滾動條美化相關外掛
也用到了彈窗、點選複製歌曲連結和歌詞連結相關功能,但是目前歌曲分享功能暫未實現、後續....
==致謝==:歌曲搜尋參照某位大佬封裝的 qq 音樂的 api,UI 介面參照另一位大神的一些解決方案,在此表示感謝
相關外掛
那麼相關使用的開源外掛有:
- jQuery 官方類庫:https://jquery.com
- layer 彈窗外掛:http://layer.layui.com
- 複製貼上庫外掛:https://www.npmjs.com/package/clipboard-js
- mCustomScrollbar 滾動條美化外掛:http://manos.malihu.gr/jquery-custom-content-scroller
- background-blur 背景圖片模糊特效外掛:https://msurguy.github.io/background-blur
還有播放、控制、歌詞解析、搜尋、載入動畫sg類庫等功能全部手寫,爽的不行
溫馨提醒
本播放器並不需要什麼特別的執行環境,直接下載開啟就能用了 ^_^
響應式優化,可在各種大小的裝置執行開啟
音樂搜尋的結果均來自 qq音樂 (後續會繼續擴大到多個平臺)
本播放器還有一些 bug,需求就是不斷滿足的,虛心請教...
談談開發
果斷使用的是 H5 播放器,十分好用
一般在做這種播放器的開發,要多多使用面向物件的開發思想
定義一個播放器物件,相關引數、方法如下:
播放器物件:krAudio
引數:
播放器:audioDom
進度條鎖定:locked:true
進度條按下的鎖:kdown
靜音的鎖:flag_volume
當前音量:curentVoice
當前播放的列表序號:Currentplay
當前播放列表歌曲總數:allItem
播放模式,1 為列表迴圈:orderModes
方法:
播放器初始化:init
設定播放的音樂地址:seturl
播放:play
暫停:stop
播放時間監聽及處理:time
時間格式化:format
下一首:next
上一首:prev
播放模式:ordermode
拖動進度條:controlTime
拖動音量條:controlVoice
上面部分的引數及方法基本涵蓋播放器該有的功能,定義好了整個播放器物件所需要的引數和方法,就可以進行具體開發了
歌詞聯動播放
具體談談這個功能的實現
歌詞解析,我之前做的==樂詩部落格==採用的是自己寫的一種歌詞解析滾動播放的方法
首先明白一般歌詞的形式是:
[00:13.80]期望飛上恬靜月球遙望每家的窗
[00:18.24]誰伴深愛細味露臺玫瑰香
這樣子的形式,利用 ajax 非同步請求到歌詞檔案內容,然後就可以進行字串裁剪,單單取出時間和歌詞,html5 播放器可以獲取到當前播放時間,就可以實現==當前播放時間==和==當前歌詞==一一對應,附上程式碼:
loadLrc :function(){//載入歌詞
var vallrc = $(".hidetextlrc").text();
//如果沒有上傳歌詞或者刪除了歌詞
if(!vallrc || $(".is_deleteLrc").text() == 1){
$(".lrc_content_notext").text("暫無歌詞");
$(".lrc_content_notext").show();
return;
}
var isHrefLrc = $(".is_href_lrc").text();
//如果是上傳的歌詞,那就要拼接上伺服器地址
if(isHrefLrc == 0) vallrc = basePath + "/" + vallrc;
$.ajax({ //非同步請求獲取本地歌詞
url:vallrc,
type:"post",
success:function(data){
//第一次分離歌詞
var lrcArr = data.split("[");
//存放分離後的歌詞
var html = "";
var lrclast = null; //記錄上一行的歌詞
var lrcmes = null; //記錄當前行的歌詞
var bofo = -1; //記錄上一行歌詞的秒數
var ms = -1; //當前這一行的秒數
for(var i = 0;i < lrcArr.length;i++){
//第二次分割歌詞,變成["03:01.08","這個世界變得更加美麗"],陣列以逗號分隔
var arr = lrcArr[i].split("]");
//取到陣列arr下標為1的歌詞部分
//將上一行的歌詞賦值給lrclast
lrclast = lrcmes;
//得到當前歌詞
lrcmes = arr[1];
//取到時間
var time = arr[0].split("."); //變成["03:01","08"]
//取到time下標為0的分鐘和秒
var ctime = time[0].split(":"); //變成["03","01"];
//將上一行的秒數賦值給bofo
bofo = ms;
//轉化成秒數
ms = ctime[0]*60 + ctime[1]*1;
//如果上一行和當前行秒數相同,則當前行秒數++ ,解決秒數相同的辦法
if(bofo == ms){
ms++;
} else if (ms >= 0){
if(!isNaN(bofo)){ // 如果是數字
var classeName = "l_"+bofo;
var concon = bofo; // bofo會自增,所以下面for迴圈條件用這個變數來代替
for(var j = 0;j < ms-concon-1;j++){
classeName += " l_"+ ++bofo;
}
if(ms>=0 && lrclast != null){
html += "<li class='"+classeName+"'>"+lrclast+"</li>";
}
}
}
}
//裝載最後一行歌詞的機制,先獲取歌曲總時間
setTimeout(function(){
var allall = krAudio.audioDom.duration;
var classlaName = "l_"+ms;
var conben = ms; //ms會自增,所以下面for迴圈條件必須用這個變數來代替
for(var j = 0;j < allall-conben-1;j++){
classlaName += " l_"+ ++ms;
}
html += "<li class='"+classlaName+"'>"+lrcmes+"</li>";
//把解析好的歌詞放入歌詞展示區中
$("#lrcly").html(html);
$("#lyrics").html(html);
},200);
}
});
// 聯動音樂播放歌詞
krAudio.audioDom.addEventListener("timeupdate",function(){
//獲取當前播放時間,獲得的是秒數
var time = this.currentTime;
//解析音樂對應的時間
var m = parseInt(time / 60);//獲取此時的分鐘
var s = parseInt(time); //轉換int型別,獲取此時的秒數
$(".l_"+s).addClass("lrcsel").siblings().removeClass("lrcsel");
//歌詞滾動條,使歌詞在中間的計算公式:
//第n行歌詞*li的高度-歌詞區域中間的li(就是包括這個li,取這個li的一半)以上的li的總高度
//區域性歌詞的控制
$(".lrc_content_box").stop().animate({
scrollTop:(($(".lrcsel").index()+1)*29 - 145)//減去偏差,使當前歌詞在中間
},240);
//全屏歌詞的控制
$("#lyrics").stop().animate({
scrollTop:(($(".lrcsel").index()+1)*24 - 168)//減去偏差,使當前歌詞在中間
},240);
});
},
這種==歌詞解析==、==聯動播放==的實現是我之前==樂詩部落格==採用的一種方案,感覺也不錯
重點來了
此次採用的是另一種歌詞解析方式,利用 js 正則表示式全部替換的方式
替換方式
var reg = /-/g; // g表示全部替換 ,要替換的字串是-
createTime = createTime.replace(reg,"/"); // 第二個引數表示替換成 /
// 替換成2018/04/03
歌詞解析
//解析歌詞
function parseLyric(lrc) {
var lyrics = lrc.split("\n");
var lrcText = {};
for(var i=0;i<lyrics.length;i++){
var lyric = decodeURIComponent(lyrics[i]);
var timeReg = /\[\d*:\d*((\.|\:)\d*)*\]/g;
var timeRegExpArr = lyric.match(timeReg);
if(!timeRegExpArr)continue;
var clause = lyric.replace(timeReg,'');
for(var k = 0,h = timeRegExpArr.length;k < h;k++) {
var t = timeRegExpArr[k];
var min = Number(String(t.match(/\[\d*/i)).slice(1)),
sec = Number(String(t.match(/\:\d*/i)).slice(1));
var time = min * 60 + sec;
lrcText[time] = clause;
}
}
return lrcText;
}
這樣子解析出來的是一個物件,存放著鍵值對
鍵:==時間(秒)==
值:==歌詞==
就可以直接做一個 for in 迴圈將每句歌詞新增到歌詞區域,將時間新增到每句歌詞的樣式控制 class 名
根據每句歌詞的時間,就可以在播放器的 timeupdate 監聽事件裡實現滾動播放歌詞了(程式碼上面有)
拖動進度條
滑鼠拖動進度條的時候,有三個監聽事件
按下:onmousedown
移動:onmousemove
彈起:onmouseup
這裡滑鼠移動事件需要放在滑鼠按下事件裡面,當滑鼠彈起時,在裡面清除移動、彈起兩個事件,以免彈起時還執行滑鼠按下拖動事件(也可以定義一把鎖來控制)
還有很多細節點的問題,上一曲下一曲臨界值、搜尋後的播放控制、列表小選單與主按鈕之間的聯動、三種播放模式(順序播放、隨機播放、單曲迴圈)等等等等... 有坑也有歡笑
截圖展示
專案連結
線上演示:Lily_music
GitHub:https://github.com/Krryxa/Lily_music
歡迎 start
部落格地址:https://ainyi.com/#/59