從零開始實現網易雲音樂播放器(3)

H5增加了很多的標籤,面試的時候,如果面試官問你H5都有哪些新標籤,你回答header、footer、nav。

這麼回答幾乎是無效的,因爲這些標籤在H5裏面的角色,相當於雞骨頭、魚刺、蘑菇腿——全是雞肋,至少你得答出來audio、video、canvas,這些纔是H5的核心功能,本文我們就重點說一下audio。

audio廣泛的應用於各種項目中,遊戲背景、各種播放器,可以說有聲音的地方就有audio,當然因爲各種限制和坑,很容易讓前端人員陷入尷尬,比如在iphone下audio 是不允許autoplay的,如果前端人員不知道這個坑,產品經理又拿微信做對比,那這個鍋前端就背定了。

所以本文通過對audio的核心知識的講解,讓小夥伴們一來不背鍋,二來不加班。

第一步非常簡單你就把audio當成圖片使用,搞出個src,剩下ul是歌曲列表,然後是一堆功能按鈕,不再贅述。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> ​ <title>網易雲音樂</title> </head> <body> <audio src="mp3/千千闕歌.mp3" id="audio" controls></audio> <h3>點擊開始播放</h3> <ul> <li> <a href="javascript:;">千千闕歌</a> </li> <li> <a href="javascript:;">時間都去哪兒了</a> </li> <li> <a href="javascript:;">小蘋果</a> </li> <li> <a href="javascript:;">夜的鋼琴曲</a> </li> <li> <a href="javascript:;">雨的印記</a> </li> </ul> <div class="progress-bar"> <div class="progress"></div> <div class="progress-btn"></div> </div> <div> <input type="button" value="上一曲" id="prev"> <input type="button" value="播放" id="play"> <input type="button" value="下一曲" id="next"> ​ <input type="button" value="單曲循環" id="singleLoop"> <input type="button" value="順序播放" id="queue"> <input type="button" value="隨機播放" id="randomQueue"> <input type="button" value="循環播放" id="menuloop"> </div> </body> </html>

這樣的播放控制條很醜,產品經理會很不滿意,當然了,如果產品經理說真好看,那你就換公司吧,我們需要隱藏控制條,然後自己用各種按鈕和標籤模擬一個。

第一個功能,播放暫停,

//播放 oPlay.onclick = function () { if (oA.paused) { this.value = '暫停' oA.play(); } else { this.value = '播放' oA.pause(); } };

然後整下一曲,

var arrSong = [ '千千闕歌', '時間都去哪兒了', '小蘋果', '夜的鋼琴曲', '雨的印記' ]; ​ //下一曲 function play() { for (var i = 0; i < aA.length; i++) { aA[i].className = ''; } aA[iNow].className = 'on'; oA.src = 'mp3/' + arrSong[iNow] + '.mp3'; oA.play(); } //下一曲 oNext.onclick = function () { iNow++; if (iNow >= arrSong.length) { iNow = 0; ​ } oPlay.value = '暫停'; play(); };

這裏大家要注意,我使用的是數組的形式,因爲數組要比單獨處理某一個音樂更方便。下面是單曲循環

//單曲循環 oSingleLoop.onclick = function () { oA.loop = !oA.loop; };

這裏涉及到一個坑,很多人會覺得我直接在mp3播放onend事件裏面在播放一次原來的音樂不就可以了嗎?

確實可以問題是麻煩,因爲自身就有了loop屬性,但是隨機播放或者整個列表重複就沒有屬性了,這裏就要使用switch case判斷。

//順序播放 oQueue.onclick = function () { oA.playState = 2; }; //隨機播放 oRandomQueue.onclick = function () { oA.playState = 3; }; //列表循環 oMenuloop.onclick = function () { oA.playState = 4; }; ​ //播放完畢,單曲循環 oA.onended = function () { switch (oA.playState) { case 2: iNow++; if (iNow < arrSong.length) { play(); } break; //隨機 case 3: iNow = rnd(0, arrSong.length); play(); break; //列表循環 case 4: iNow++; if (iNow > arrSong.length) iNow = 0; play(); break; ​ } };

這裏算是一個功能實現技巧,通過開關,上面說這些都很簡單,我們實現一個看起來複雜其實非常簡單的的功能,進度條,其實進度就是當前時間/總時間,這裏要用一個timeupdate事件,因爲播放的過程中時間是不斷變化的,

oA.addEventListener('timeupdate', activeProgressBar, false); function activeProgressBar() { var percentNum = Math.floor((oA.currentTime / oA.duration) * 10000) / 100 + '%'; progress.style.width = percentNum; progressBtn.style.left = percentNum; }

這裏,給大家順便留一個作業,如何實現進度條拖拽改變,播放進度呢?提示:

var percentNum = (e.targetTouches[0].pageX - progressBar.getBoundingClientRect().left) / progressBar.getBoundingClientRect().width;

最後給大家說兩個坑,第一個坑是mp3加載,建議使用preloadjs 而不是preload屬性,

第二給大家一個事件,

audio.addEventListener('loadedmetadata', function() { console.log("Playing " + audio.src + ", for: " + audio.duration + "seconds."); audio.play(); });

這個事件用在頁面加載完,但是mp3如果沒有加載到位會出現獲取音樂時長NaN問題,用這個就OK了。

最後給大家留一個作業:

實現網易雲音樂App的上一曲、下一曲、單曲、列表循環、順序播放,以及播放進度控制CD封面旋轉功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章