《從案例中學(xué)習(xí)JavaScript》之酷炫音樂播放器(二)

上一節(jié)傳送門:http://www.reibang.com/p/14dd440a8bc3

本節(jié)實(shí)現(xiàn)了:

  • 歌曲切換
  • 圖標(biāo)轉(zhuǎn)動(dòng)
  • 顯示歌曲信息

下一節(jié)計(jì)劃:

  • 添加音軌
  • 進(jìn)度條

小demo已經(jīng)寫好拒贱,不用擔(dān)心跳票啥的宛徊。

繼續(xù)上一節(jié)的內(nèi)容,我們?cè)诶L制好播放器的雛形之后逻澳,就可以考慮將一些工具性質(zhì)的方法封裝起來了闸天,比如,我們多次用到dom和_center方法斜做,不如將它們歸為一類苞氮,做為一個(gè)工具包來調(diào)用。

上代碼:

var utils = {
    _center : function(dom){
        dom.style.position = 'absolute';
        dom.style.top = '50%';
        dom.style.left = '50%';
        dom.style['margin-top'] = - dom.offsetHeight / 2 + 'px';
        dom.style['margin-left'] = - dom.offsetWidth / 2 + 'px';
    },

    dom : function(id){
        if(id.toString().indexOf('#') != -1) {
            id = id.replace('#','');
        }
        return document.getElementById(id);
    },
}

然后我們就可以這樣調(diào)用了:

var musicDom = utils.dom('#music');
var musicIcon = utils.dom('#music-icon');
utils._center(musicDom);
utils._center(musicIcon);

util是工具的意思瓤逼,這樣是不是清晰多了呢葱淳?

然后進(jìn)行js打包:

引入:

<script type="text/javascript" src="js/util.js"></script>

用閉包的形式將util包裹起來,再掛在window對(duì)象下面抛姑,以防止命名重復(fù)赞厕。一個(gè)簡(jiǎn)單的工具包就這樣做好啦!

;(function(win){
    var utils = {
        _center : function(dom){
            dom.style.position = 'absolute';
            dom.style.top = '50%';
            dom.style.left = '50%';
            dom.style['margin-top'] = - dom.offsetHeight / 2 + 'px';
            dom.style['margin-left'] = - dom.offsetWidth / 2 + 'px';
        },

        dom : function(id){
            if(id.toString().indexOf('#') != -1) {
                id = id.replace('#','');
            }
            return document.getElementById(id);
        },
    }

    win.utils = utils;
})(window);

同時(shí)定硝,我們把css也單獨(dú)整出去皿桑,不要放在頁面里,那樣會(huì)顯得頁面特別龐大蔬啡,頁面應(yīng)該整潔和精簡(jiǎn)诲侮。當(dāng)一個(gè)模子畫出來之后,我一般都會(huì)將css整出去箱蟆。

.music {
    width: 200px;
    height:300px;
    background:#333;
    border-radius: 5px;
    box-shadow: 3px -3px 1px #666;
    position: relative; /*center方法已經(jīng)將position設(shè)置為absolute了沟绪,這一行不起作用*/
}
.music .screen {
    height:70%;
    width:96%;
    background: linear-gradient(#403d3d,65%,#5f5b5b);
    margin-left:2%;
    margin-top: 2%;
    position: relative;

}

.music .screen i {
    color:#fff;
    font-size: 88px;
}

.music .buttons i {
    color:#fff;
    font-size: 24px;
    margin-left: 28px;
    position: relative;
    top:25px;
}

.music .buttons i:hover {
    cursor: pointer;
}


.music .buttons {
    height:25%;
    width:96%;
    margin-left:2%;
    margin-top: 2%;
}
<link rel="stylesheet" type="text/css" href="css/index.css"/>

這樣一來,頁面就簡(jiǎn)潔多了空猜!

接下來绽慈,讓我們愉快地開發(fā)功能吧!

1. 開始和暫停按鈕之間的切換

/* 獲取開始按鈕 */
var playDom = utils.dom('#play');

然后辈毯,給它綁定一個(gè)點(diǎn)擊事件

playDom.onclick = function(){
    alert('play');
}

這說明綁定事件成功了坝疼。

將暫停按鈕加上去,默認(rèn)是隱藏的谆沃。

上一節(jié)中出現(xiàn)了圖標(biāo)編碼格式?jīng)_突的問題钝凶,因此我把iconfont的引入改成了下面的方式:

<i id='pause' class="iconfont icon-zanting" style="display:none"></i>

按鈕切換的邏輯代碼:

/* 獲取開始按鈕 */
var playDom =  utils.dom('#play');
/* 獲取暫停按鈕 */
var pauseDom = utils.dom('#pause');

playDom.onclick = function(){
    this.style.display = 'none';
    pauseDom.style.display = 'inline';
}

pauseDom.onclick = function(){
    this.style.display = 'none';
    playDom.style.display = 'inline';
}

效果(截屏效果一般,漸變色沒顯示唁影,大伙先將就著看吧):

222.gif

2. 音樂播放和暫停

還記得上一節(jié)封裝的musicBox對(duì)象嗎耕陷?

播放和暫停的核心方法是這樣的:

play : function(index){
    this.musicDom.src = this.songs[index];
    this.musicDom.play();
},

//暫停音樂
stop : function(){
    this.musicDom.pause();
},

3. 代碼重構(gòu)和歌曲切換的實(shí)現(xiàn)

今天掂名,我對(duì)musicBox進(jìn)行了一次簡(jiǎn)單的重構(gòu),代碼如下:

var musicBox= {

    musicDom : null, //播放器對(duì)象
    songs : [],      //歌曲目錄哟沫,用數(shù)組來存儲(chǔ)
    index : 0,       //當(dāng)前播放的歌曲索引

    //初始化音樂盒
    init : function(themeIndex){
        this.musicDom = document.createElement('audio');
        document.body.appendChild(this.musicDom);
    },

    //添加一首音樂
    add : function(src){
        this.songs.push(src);
    },

    //根據(jù)數(shù)組下標(biāo)決定播放哪一首歌
    play : function(){
        this.musicDom.src = this.songs[this.index];
        this.musicDom.play();

    },

    //暫停音樂
    stop : function(){
        this.musicDom.pause();
    },

    //下一首
    next : function(){
        var len = this.songs.length;
        //判斷是否是有效的索引
        if((this.index + 1) >= 0 && this.index < len){
            this.index ++;
            //如果已經(jīng)是最后一首饺蔑,就跳到第一首
            if(this.index == len){
                this.index = 0;
            }
            this.play();
        }
    },

    //上一首
    prev : function(){
        var len = this.songs.length;
        //判斷是否是有效的索引
        if((this.index + 1) >= 0 && this.index  < len){
            //如果已經(jīng)是第一首,就跳到最后一首
            if(this.index == 0){
                this.index = len;
            }
            this.index --;
            this.play();
        }
    }

}

不同點(diǎn)如下:
1.添加音樂索引index南用,取消了play方法的參數(shù)膀钠。
2.實(shí)現(xiàn)了上一首和下一首的邏輯代碼
3.默認(rèn)音樂為第一首

順便添加了幾首音樂。

現(xiàn)在我們就來調(diào)用看看吧裹虫,當(dāng)點(diǎn)擊播放按鈕的時(shí)候肿嘲,就播放指定的歌曲。點(diǎn)擊暫停按鈕就停止播放筑公。

4. 測(cè)試

var musicDom = utils.dom('#music');
var musicIcon = utils.dom('#music-icon');
utils._center(musicDom);
utils._center(musicIcon);


musicBox.init(); //初始化
musicBox.add('mp3/火影忍者主題曲.mp3');
musicBox.add('mp3/曲婉婷 - 我的歌聲里.mp3');
musicBox.add('mp3/夜空中最亮的星.mp3');
musicBox.add('mp3/班得瑞 - 雪之夢(mèng).mp3');
musicBox.add('mp3/超級(jí)好聽的龍貓輕音樂.mp3');
/* 獲取開始按鈕 */
var playDom =  utils.dom('#play');
/* 獲取暫停按鈕 */
var pauseDom = utils.dom('#pause');
/* 獲取下一首按鈕 */
var nextDom = utils.dom('#next');
/* 獲取上一首按鈕 */
var prevDom = utils.dom('#prev');

//播放按鈕
playDom.onclick = function(){
    this.style.display = 'none';
    pauseDom.style.display = 'inline';
    //播放音樂
    musicBox.play();
}

//暫停按鈕
pauseDom.onclick = function(){
    this.style.display = 'none';
    playDom.style.display = 'inline';
    musicBox.stop();
}

//下一首
nextDom.onclick = function(){
    musicBox.next();
    //當(dāng)直接點(diǎn)擊下一首的時(shí)候雳窟,同時(shí)改變播放按鈕為暫停的樣式
    playDom.style.display = 'none';
    pauseDom.style.display = 'inline';
}

//上一首
prevDom.onclick = function(){
    musicBox.prev();
    //當(dāng)直接點(diǎn)擊下一首的時(shí)候,同時(shí)改變播放按鈕為暫停的樣式
    playDom.style.display = 'none';
    pauseDom.style.display = 'inline';
}

成功運(yùn)行起來了匣屡,雖然有聲音封救,但是還看不出屏幕的變化,所以捣作,接下來誉结,我們做一點(diǎn)有趣的事情。

5. 隨著歌曲的播放券躁,讓音樂圖標(biāo)轉(zhuǎn)動(dòng)起來

關(guān)于這個(gè)惩坑,就需要用到css3的一個(gè)知識(shí)點(diǎn)了,就是關(guān)鍵幀也拜。因?yàn)椴皇菍iT開貼講解css3以舒,所以這邊我就簡(jiǎn)單說明一下了。

像這樣:

@keyframes move{
    0% {transform: rotate(0deg)}
    100% {transform: rotate(360deg)}
}
.r {
    animation: move 1s linear infinite;
}

簡(jiǎn)單來說慢哈,就是我們定義了一個(gè)名字叫r的class蔓钟,動(dòng)畫效果采用名字叫move的關(guān)鍵幀。transform是轉(zhuǎn)換的意思卵贱,因?yàn)橛⑽脑~根trans就有從一個(gè)狀態(tài)變到另一個(gè)狀態(tài)的涵義滥沫,這是比較好理解的,而deg是角度的意思艰赞。

@keyframes move{
    0% {transform: rotate(0deg)}
    100% {transform: rotate(360deg)}
}

用以上這段代碼佣谐,我們制作了一個(gè)關(guān)鍵幀動(dòng)畫,名字叫move方妖,它將一個(gè)元素的位置從0度變化到360度,就是轉(zhuǎn)了一圈罚攀。

.r {
    animation: move 1s linear infinite;
}
  • liner表示線性党觅,這個(gè)屬性會(huì)讓擁有該class的dom元素連續(xù)地旋轉(zhuǎn)雌澄。
  • infinite表示不停止、無限杯瞻,不然的話轉(zhuǎn)一圈就結(jié)束了镐牺。

現(xiàn)在,我們給音樂圖標(biāo)加上轉(zhuǎn)動(dòng)樣式:

<i id='music-icon'  class="iconfont icon-yinle r"></i>

在這里我去掉了該元素的定位方法魁莉,而繼續(xù)采用css的方式來居中睬涧。

.music .screen i {
    color:#fff;
    font-size: 88px;
    position: absolute;
    left: 50%;
    top : 50%;
    margin-left: -40px;
    margin-top: -48px;
}
截圖原因,效果看起來不咋地旗唁,其實(shí)它的轉(zhuǎn)動(dòng)是非常平滑的畦浓,我也不清楚為啥截圖后變成了這個(gè)樣子。
rotate.gif

終于轉(zhuǎn)起來了检疫,核心的操作就是給圖標(biāo)添加一個(gè)css類而已讶请。

現(xiàn)在,我們希望在點(diǎn)擊開始按鈕的時(shí)候屎媳,就轉(zhuǎn)動(dòng)圖標(biāo)夺溢。點(diǎn)擊暫停就移除轉(zhuǎn)動(dòng)的css類。

先給util工具包擴(kuò)展下面這幾個(gè)方法:

/*判斷dom元素是否擁有某個(gè)class類*/
hasClass : function(obj, cls) {
    return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
        },

/*給dom元素增加某個(gè)class類*/
addClass : function(obj, cls) {
     if (!this.hasClass(obj, cls)) obj.className += " " + cls;
},

/*移除dom元素中的某個(gè)class類*/
removeClass : function(obj, cls) {
    if (this.hasClass(obj, cls)) {
        var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
        obj.className = obj.className.replace(reg, ' ');
    }
},

/*該方法檢查每個(gè)元素中指定的類烛谊。如果不存在則添加類风响,如果已設(shè)置則刪除之。這就是所謂的切換效果丹禀。*/
toggleClass : function(obj,cls){
    if(hasClass(obj,cls)){
        removeClass(obj, cls);
    }else{
        addClass(obj, cls);
    }
}

6. 重寫后的按鈕事件

//播放按鈕
playDom.onclick = function(){
    this.style.display = 'none';
    pauseDom.style.display = 'inline';
    utils.addClass(musicIcon,'r');
    //播放音樂
    musicBox.play();
}

//暫停按鈕
pauseDom.onclick = function(){
    this.style.display = 'none';
    playDom.style.display = 'inline';
    utils.removeClass(musicIcon,'r');
    musicBox.stop();
}

//下一首
nextDom.onclick = function(){
    musicBox.next();
    //當(dāng)直接點(diǎn)擊下一首的時(shí)候状勤,同時(shí)改變播放按鈕為暫停的樣式
    playDom.style.display = 'none';
    pauseDom.style.display = 'inline';
    utils.addClass(musicIcon,'r');
}

//上一首
prevDom.onclick = function(){
    musicBox.prev();
    //當(dāng)直接點(diǎn)擊下一首的時(shí)候,同時(shí)改變播放按鈕為暫停的樣式
    playDom.style.display = 'none';
    pauseDom.style.display = 'inline';
    utils.addClass(musicIcon,'r');
}

效果:

audio.gif

7. 顯示正在播放的音樂

.music .info {
    position: absolute;
    display: inline-block;
    width: 80%;
    height: 30px;
    left: 15px;
    top: 20px;
    text-align: center;
    color: #eee;
    font-family:黑體;
    font-size: 14px;
}
<div id='music' class='music'>
    <div class='screen'>
        <i id='music-icon'  class="iconfont icon-yinle"></i>
    </div>
    <div class='buttons'>
        <i id='prev' class="iconfont icon-icon"></i>
        <i id='play' class="iconfont icon-bofanganniu"></i>
        <i id='pause' class="iconfont icon-zanting" style="display:none"></i>
        <i id='next' class="iconfont icon-icon1"></i>
    </div>
    <span id='info' class='info'></span>

</div>

然后在musicBox對(duì)象中添加一個(gè)獲取歌曲信息的方法:

/*獲取當(dāng)前歌曲的信息*/
getCurrentSong : function(){
    var info = this.songs[this.index];
    info = info.split('/')[1];
    info = info.split('.')[0];
    return '正在播放:' + info;
}

然后湃崩,在按鈕的點(diǎn)擊事件中荧降,只需要加上下面的代碼,即可獲取實(shí)時(shí)的歌曲信息啦攒读!

先獲取信息欄:

/* 獲取歌曲的信息欄 */
var infoDom = utils.dom('#info');

改寫按鈕點(diǎn)擊的事件:

infoDom.innerHTML = ''; //先清空上一次的信息
infoDom.innerHTML = musicBox.getCurrentSong();//顯示當(dāng)前的歌曲信息

效果:

這一節(jié)到此告一段落了朵诫,下一節(jié),我們來做音軌薄扁。

悠閑的午后剪返,品著剛泡好的茶

tea.jpeg

聽著美妙的音樂,也是一種享受吧邓梅。

20120912165608_S5Z2S.jpg

享受編程的樂趣脱盲,懷著感恩的心去體會(huì)每一天生活中的細(xì)節(jié)。

本章結(jié)束 ...

剽悍一小兔日缨,電氣自動(dòng)化畢業(yè)钱反。
參加工作后對(duì)計(jì)算機(jī)感興趣,深知初學(xué)編程之艱辛。
希望將自己所學(xué)記錄下來面哥,給初學(xué)者一點(diǎn)幫助哎壳。

免責(zé)聲明: 博客中所有的圖片素材均來自百度搜索,僅供學(xué)習(xí)交流尚卫,如有問題請(qǐng)聯(lián)系我归榕,侵立刪,謝謝吱涉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刹泄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子怎爵,更是在濱河造成了極大的恐慌特石,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疙咸,死亡現(xiàn)場(chǎng)離奇詭異县匠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)撒轮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門乞旦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人题山,你說我怎么就攤上這事兰粉。” “怎么了顶瞳?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵玖姑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我慨菱,道長(zhǎng)焰络,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任符喝,我火速辦了婚禮闪彼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘协饲。我一直安慰自己畏腕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布茉稠。 她就那樣靜靜地躺著描馅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪而线。 梳的紋絲不亂的頭發(fā)上铭污,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天恋日,我揣著相機(jī)與錄音,去河邊找鬼况凉。 笑死谚鄙,一個(gè)胖子當(dāng)著我的面吹牛各拷,可吹牛的內(nèi)容都是我干的刁绒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼烤黍,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼知市!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起速蕊,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤嫂丙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后规哲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跟啤,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年唉锌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了隅肥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袄简,死狀恐怖腥放,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绿语,我是刑警寧澤秃症,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站吕粹,受9級(jí)特大地震影響种柑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匹耕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一聚请、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泌神,春花似錦良漱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至损趋,卻和暖如春患久,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工蒋失, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留返帕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓篙挽,卻偏偏與公主長(zhǎng)得像荆萤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铣卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容