摘要:前些天偷臺風的閑暇時寫了一個移動端音樂播放器,作為練手項目。有的歌詞周杰倫算什么男人格式是時間點時間歌詞創建映射首先以將歌詞字符串分割成以時間點文字的數組,但由于這樣分割之后最后一個元素是空的,所以用刪除最后一個元素。
這段時間公司一直在做一個PC的教育類單頁應用,龐大復雜,涉及非常多H5的知識,音頻就是其中的一部分。前些天偷臺風的閑暇時寫了一個移動端音樂播放器,作為練手項目。
在線地址:請猛擊這里
源碼:請猛擊這里
注意:使用PC瀏覽最好打開移動設備模式,使用移動設備瀏覽需要關閉無痕瀏覽模式(否則無法使用本地存儲,一般瀏覽器都是默認不開啟),項目需要在本地服務器或線上服務器運行,以file:///形式的地址打開是無法進行ajax請求的,從而無法看到音樂數據。
播放器的基礎操作,上一首,下一首(順序播放、隨機播放、單曲循環),播放暫停,滑動時間軸的歌詞定位
初始handlebar模板渲染音樂列表數據,下拉滾動加載音樂列表數據。
歌曲列表可添加喜愛音樂,于下次刷新時更新喜愛音樂列表,基于HTML5本地存儲。
布局采用rem布局,自適應移動端手機設備。
iconfont在線圖標應用的使用
項目目錄文件結構css:存放樣式文件
lib:?存放公共腳本庫
js:?存放項目腳本文件
img:?存放圖片
fonts:?項目字體文件
res:?項目音樂資源
ui:項目ui文件(psd)
// ============================配置變量================================ var rootPath = window.location.href.replace(//w+.w+/, "/"); var Settings = { playmode: 0, //0列表循環,1隨機,2為單曲循環 volume: 0.5, //音量 initNum: 10, //列表初始化歌曲數 reqNum: 10 //后續請求歌曲數 }; // ============================工具函數================================ var Util = (function() { return { } })() // ============================Dom選擇器================================ var Dom = { } // ============================全局變量================================ var winH = $(window).height(); var songNum = 0; //當前列表歌曲數目 var lrcHighIndex = 0; // 歌詞高亮索引 var lrcMoveIndex = 0; // 歌詞移動單位索引 var moveDis = 0; // 單句歌詞每次移動距離 var duration = 0; // 當前歌曲的時間 var index = 0; //當前播放歌曲的索引 var songInfo = null; // 當前歌曲信息 var songModelUI = null; // 當前歌曲UI模型 var timeArr = []; //當前歌曲時間數組 var formatTimeArr = []; //當前歌曲時間數組(格式化為秒數) // ============================入口函數================================ function main() { initUIFrame(); var initModel = PlayerModel(); var songListUI = ModelUIFrame(Dom.songListContainer); var lsongListUI = ModelUIFrame(Dom.lSongListContainer); initModel.getSongList("data/data.json", function(data) { // 生成所有歌曲列表 songListUI.renderList(data, 0, null, function() { songListUI.updateList(); }); // 生成喜愛歌曲列表 initModel.getLoveSongArr(function(lSongArr) { lsongListUI.renderList(data, 1, lSongArr); }); // 添加動畫 Util.addAnimationDelay(Dom.song); // 保存歌詞數據 initModel.saveLyric(data); }); EventHandler(); } // ============================初始化UI函數================================ function initUIFrame() { } // ============================實現數據交互方法================================ function PlayerModel() { } // ============================模型動態UI模塊================================ function ModelUIFrame(container) { } // ============================事件綁定模塊================================ function EventHandler() { } // 調用入口函數 main();功能點詳解 Handlebar.js初次渲染及滾動加載
使用前端模板優點是把數據和結構分離出來,代碼更清晰。但后來發現handlerbar.js似乎無法在js中示例模板對象,而html中的handlebar在初次進入頁面便會被編譯了,因此后續添加音樂還是采用傳統的拼接字符串的方式,如果你有更優雅的動態加載方式,歡迎討論交流。
html:handlebars模板包含在script標簽之中并且type類型為”text/x-handlebars-template”,在初始化頁面的時候根據js獲取數據植入后就渲染出相應的html。
js:
function renderAllList(data) { var preTpl; var lsongArr = Util.getItem("lsonglist") === null ? [] : JSON.parse(Util.getItem("lsonglist")); // 生成列表 if (!sListTpl) { // 后續動態生成歌曲 var tpl = ""; var songIndex = songNum; $.each(data, function(index, el) { if (index >= songIndex && index < songIndex + Settings.reqNum) { tpl += "
大體上指的是html根元素上定義一個字體大小,然后css樣式定義時使用rem作為單位,包括margin、paffffding、用于絕對定位的單位等等。然后js根據手機設備的屏幕大小,改變根字體的大小,這樣整個頁面也會跟著相應的縮小或放大。
更多詳解,請看這一篇文章《移動端自適應布局解決方案——rem》,您可以猛擊這里跳轉。
目前音樂播放器的歌詞同步顯示大概有兩種,一種是精確到單個文字,一種是精確到單行歌詞。本文實現的是第二種。
整體實現思路頁面初始化時,請求歌曲數據json(本地json文件模擬),其中歌名、歌手、圖片等按需渲染到html中,將歌詞存儲到localStorage中。此時,F12打開chrome調試器,進入Application-LocalStorage可以看到:
點擊一首歌進入播放頁面后,歌詞就會從本地存儲中讀取,此時你會看到生成這樣的歌詞結構:
每一行歌詞都將要將歌詞時間綁定在data-point上,監聽歌曲播放的timeupdate事件,當歌曲的時間(經過取整處理)與當前data-point值相等時,就為當前歌詞高亮(相當于給p添加current類名),并且根據當前高亮歌詞的index索引將整個歌詞盒子向上移動p標簽的高度+margin-top的高度。
lrc歌詞的結構來自網易云音樂的歌詞數據:
[00:14.64]如果不是那鏡子 [00:16.73]不像你不藏秘密 [00:21.26]我還不肯相信 [00:23.02]沒有你我的笑更美麗 [00:28.99]那天聽你在電話里略帶抱歉的關心 [00:16.959]摘一顆蘋果 [00:19.800]等你從門前經過 [00:22.700]送到你的手中幫你解渴 [00:25.570]像夏天的可樂 [00:00.00] 作曲 : 周杰倫 [00:01.00] 作詞 : 周杰倫 [00:05.620] [00:37.980]親吻你的手
可以看到格式 = [時間點] + 要顯示的文字 +
這里有兩個坑需要注意:
有的歌詞秒數是精確到小數點后兩位,有的是三位。
有的歌詞(周杰倫《算什么男人》)格式是[時間點]+
首先以n將歌詞字符串分割成以[時間點]文字的數組,但由于這樣分割之后最后一個元素是空的,所以用tempArr.splice(-1, 1)刪除最后一個元素。
接下來循環遍歷這個臨時數組,由于上面提到的秒數精確度的問題,所以判斷一下index為9是否為數字,若為數字則將該位數字刪除。(采用字符串截取方式,若你對js字符串方法不熟悉,可以猛擊這里)
經過這樣的處理之后,臨時數組的元素格式不再有區別了,此時再進行字符串截取,將截取到的時間點放入timeArr,將截取的歌詞放入lyricArr,并以返回保存著這兩個變量的對象。
function createArrMap(lyric) { var timeArr = [], lyricArr = []; var tempArr = lyric.split(" "); tempArr.splice(-1, 1); var tempStr = ""; $(tempArr).each(function(index) { tempStr = this; if (tempStr.charAt(9).match(/d/) !== null) { tempStr = tempStr.substring(0, 9) + tempStr.substring(10); } timeArr.push(tempStr.substring(0, 10)); lyricArr.push(tempStr.substring(10)); }); return { timeArr: timeArr, lyricArr: lyricArr }; }生成歌詞
由于上面歌詞格式造成時間點對應的歌詞為空,此時如果渲染出一個
標簽的高度將為0,這會影響歌詞向上移動距離的不統一。因此下面作出個判斷如果為空,則替換為“————–”。(為空的時候大多數是歌曲中間停頓或過渡的時候)
function renderLyric(songinfo) { var arrMap = Util.createArrMap(songinfo.lyric); var tpl = ""; $.each(arrMap.lyricArr, function(index, lyric) { var lyricContent = lyric === "" ? "--------------" : lyric; tpl += "歌詞同步" + lyricContent + "
"; }); Dom.lrcwrap.html(tpl); }
歌詞同步我寫在了syncLyric方法中,監聽audio元素的timeupdate事件調用。
這個方法接收兩個參數,第一個是當前播放歌曲時間(秒),第二個是轉化為秒數的時間點數組。
如果當前時間>=時間點,那么高亮當前歌詞(以lrcHighIndex)存儲,并且lrcHighIndex自增1。
當歌詞高亮索引lrcHighIndex>=1即歌詞高亮不為第一句時,計算索引并讓歌詞盒子向上移動。
function syncLyric(curS, formatTimeArr) { if (Math.floor(curS) >= formatTimeArr[lrcHighIndex]) { Dom.lrc.eq(lrcHighIndex).addClass("current").siblings().removeClass("current"); if (lrcHighIndex >= 1) { lrcMoveIndex = lrcHighIndex - 2; moveDis += Util.getMoveDis(lrcMoveIndex); Dom.lrcwrap.animate({ "top": "-" + moveDis + "px" }, 100); lrcMoveIndex++; } lrcHighIndex++; } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/80730.html
摘要:基于等開發一款移動端音樂,界面參考了安卓版的網易云音樂布局適配常見移動端。圖標使用阿里巴巴圖標庫,中間的唱片旋轉動畫使用了實現。搜索功能實現功能搜索歌手歌單歌曲熱門搜索數據節流上拉刷新保存搜索記錄。 基于 Vue(2.5) + vuex + vue-router + vue-axios +better-scroll + Scss + ES6 等開發一款移動端音樂 WebApp,UI ...
閱讀 2668·2023-04-26 02:44
閱讀 8573·2021-11-22 14:44
閱讀 2127·2021-09-27 13:36
閱讀 2505·2021-09-08 10:43
閱讀 687·2019-08-30 15:56
閱讀 1399·2019-08-30 15:55
閱讀 2893·2019-08-28 18:12
閱讀 2835·2019-08-26 13:50