個人小作品之迷你音樂播放器(移動端)

關於viewport


viewport是用戶網頁的可視區域,中文可稱爲“可視區”。

手機瀏覽器是將頁面放在一個虛擬的窗口(viewport)中,通常這個窗口比屏幕寬,這樣就不用把每個頁面都擠在一個窗口中,用戶通過平移和縮放來查看頁面的不同的部分。


設置viewport

一個常用於針對移動頁面優化過的頁面的viewport meta 標籤如下:

    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">

其中:
  • width:控制 viewport 的大小,可以指定的一個值,如 600,或者特殊的值,如 device-width 爲設備的寬度(單位爲縮放爲 100% 時的 CSS 的像素)。
  • height:和 width 相對應,指定高度。
  • initial-scale:初始縮放比例,也即是當頁面第一次 load 的時候縮放比例。
  • maximum-scale:允許用戶縮放到的最大比例
  • minimum-scale:允許用戶縮放到的最小比例

本作品源代碼GitHub:點擊查看本作品源代碼


開始製作播放器

播放器的效果圖爲:




本次關於移動端的頁面製作採用rem爲單位。

rem:相對單位,相對於根目錄<html>的font-size,根據設備的寬度自動改變


HTML部分的佈局:使用HTML5標籤進行佈局

<!doctype html>
<html lang="zh-en">
  <head>
    <meta charset="utf-8">
    <title>迷你音樂播放器</title>
    <link rel="stylesheet" href="css/style.css">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
  </head>
  <body>
    <header>
      <h3 class="musicTitle"></h3>
    </header>
    <section class="singer">
      <div>
        <img src="images/tx.jpg">
      </div>
    </section>
    <!-- 進度條部分 -->
    <section class="progress">
      <div class="bg"></div>
      <div class="bar"></div>
    </section>
    <!-- 按鈕部分 -->
    <section class="btn">
      <div class="prev iconfont"></div>
      <div class="play iconfont"></div>
      <div class="pause iconfont"></div>
      <div class="next iconfont"></div>
    </section>
    <!-- 音頻播放部分 -->
    <audio src="mp3/" id="myMusic"></audio>
  
  <script src="js/js.js"></script>
  </body>
</html>


其中:

  • 進度條原理:就是不斷改變 進度條的背景寬度 來 實現進度條的顏色改變部分。

<!-- 進度條部分 -->
<section class="progress">
  <div class="bg"></div>
  <div class="bar"></div>
</section>



CSS部分:

在實現進度條功能時:
  • 不斷改變 進度條的背景寬度 來 實現 進度條顏色部分。
  • 對於小滑塊部分,使用CSS3中的tranform: translate();屬性來代替定位屬性。
transform: translate(0rem, -.15rem); /* 代替絕對定位 */

分別爲水平方向、垂直方向上的偏移。

  • 對於按鈕部分,是使用 阿里圖標 來代替圖片,稱爲 IcomFont圖標。
如:


在HTML中輸入對應的代碼就相對應按鈕,如:輸入“&#xe6de”就相當於“上一曲按鈕”。

使用這種圖標分三個步驟:使用之前需要下載圖標文件:阿里矢量圖標管網,下載完成後:將裏面的文件保存在一個文件夾裏面,接着:
  • 第一步,使用font-face聲明字體:
@font-face {
  font-family: 'iconfont';
  src: url('../iconfont/iconfont.eot');
  src: url('../iconfont/iconfont.eot?#iefix') format('embedded-opentype'),
  url('../iconfont/iconfont.woff') format('woff'),
  url('../iconfont/iconfont.ttf') format('truetype'),
  url('../iconfont/iconfont.svg#iconfont') format('svg');
}

其中,"font-family"爲自定義的字體名稱,注:src、url屬性路徑要正確。

  • 第二步,定義使用iconfont的樣式:
.iconfont{
  font-family:"iconfont" !important;
  font-size: 1.5rem;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -webkit-text-stroke-width: 0.2px;
  -moz-osx-font-smoothing: grayscale;
  color: #fff;
}


  • 第三步,挑選相應圖標並獲取相應字體編碼,應用於頁面
<div class="prev iconfont"></div>
<div class="play iconfont"></div>
<div class="pause iconfont"></div>
<div class="next iconfont"></div>

效果:


注意:在佈局時,需要先隱藏一個播放按鈕。



CSS部分代碼爲:

* {
  padding: 0;
  margin: 0;
}


body {
  background: url("../images/bg.jpg");
}


header {
  width: 100%;
  height: 2rem;
  text-align: center;
  color: #fff;
}

/* 自定義字體,阿里圖標 */
@font-face {
  font-family: 'iconfont';
  src: url('../iconfont/iconfont.eot');
  src: url('../iconfont/iconfont.eot?#iefix') format('embedded-opentype'),
  url('../iconfont/iconfont.woff') format('woff'),
  url('../iconfont/iconfont.ttf') format('truetype'),
  url('../iconfont/iconfont.svg#iconfont') format('svg');
}

.iconfont{
  font-family:"iconfont" !important;
  font-size: 1.5rem;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -webkit-text-stroke-width: 0.2px;
  -moz-osx-font-smoothing: grayscale;
  color: #fff;
}


header h3 {
  font-size: 0.5rem;
  line-height: 1.3rem;
}


header p {
  font-size: 0.3rem;
}


.singer {
  width: 8rem;
  height: 8rem;
  border: 1px solid #fff;
  margin: auto;
  border-radius: 50%;
}

.singer div {
  width: 7.6rem;
  height: 7.6rem; 
  margin: .2rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .5);
}

.rotate {
  animation: rot 10s linear infinite;
}

@keyframes rot {
  to {
    transform: rotate(360deg);
  }
}

.singer div  img {
  width: 7rem;
  height: 7rem;
  border-radius: 50%;
  margin: 0.3rem;
}


.progress {
  width: 9rem;
  height: 0.1rem;
  background: #c03;
  margin: 1rem auto;
}


.bg {
  width: 0;
  height: 0.1rem;
  background: #0f9
}


.bar {
  width: .2rem;
  height: .2rem;
  background: blue;
  border-radius: 50%;
  transform: translate(0rem, -.15rem); /* 代替絕對定位 */
}


.btn {
  width: 8rem;
  margin: auto;
}

.btn div {
  float: left;
  margin: .5rem;
}


.pause {
  display: none;
}




JS部分:


播放器功能的實現:

  • 點擊按鈕實現播放/暫停功能。

先獲取表示播放和暫停功能的按鈕:

var oPlay = document.getElementsByClassName("play")[0];
var oPause = document.getElementsByClassName("pause")[0];

點擊實現播放/暫停:

/* 點擊實現播放功能 */
oPlay.onclick = function () {   
    myMusic.play();
    oPause.style.display = "block";
    this.style.display = "none";
    oSinger.className = "singer rotate";
};

/* 點擊實現暫停功能 */
oPause.onclick = function () {
    myMusic.pause();
    oPlay.style.display = "block";
    this.style.display = "none";
    oSinger.className = "singer";
};


  • 進度條功能的實現:
a、首先要獲取音樂的播放進度,即添加事件、更新時間。

/* 進度條功能 */
var w = oProgress.offsetWidth - oBar.offsetWidth; //計算小滑塊可移動的範圍
myMusic.addEventListener("timeupdate", function () {
    var s = this.currentTime/this.duration; //當前時間/總時間
    oBar.style.transform = "translate("+s*w +"px, -0.15rem)"; //滑塊隨音樂移動
    oBg.style.width = s*w + "px";
});

其中:

timeupdate:更新事件

currentTime:當前播放的時間

duration:音樂的總時間


c、拖拽進度條播放音樂/觸屏事件拖拽進度條

//觸屏事件拖拽進度條
var x = 0, l = 0, _left = 0;
oBar.addEventListener("touchstart", function (e) {
    var x = e.changedTouches[0].pageX; //獲取手指按下去的位置
    document.addEventListener("touchmove", move);
    document.addEventListener("touchend", function () { //觸屏結束後需要解綁觸屏事件
        l = _left;
    });
});

function move(e) {
    var x1 = e.changedTouches[0].pageX;
    var _left = x1 -x + l;
    if (_left < 0) {
        _left = 0;
    } else if (_left > w) {
        _left = w;
    }
    oBar.style.transform = "translate("+_left+"px, -0.15rem)";
    oBg.style.width = _left + "px";
    myMusic.currentTime = _left/w*myMusic.duration;
}


其中,

touchstart:觸屏開始事件

touchend:觸屏結束事件

changedTouches:觸發事件的手指列表數

觸發事件結束需要解綁事件(touchend)

硬件加速:是投影,沒有重新渲染dome



關於歌曲列表技巧:使用數組來保存歌曲,通過改變音樂的路徑來實現換曲功能。



自動換曲功能:

可以使用audio屬性的ended事件(媒體已播放到末尾,播放停止)來實現自動換曲功能。

//自動播放下一曲
myMusic.addEventListener("ended", function (e){
    n ++;
    if (n > 4) {
        myMusic.pause();
        myMusic.src = "";
        oSinger.className = "singer";
        oBg.style.width = 0;
        oBar.style.transform = "translate("+0+"px, -0.15rem)";
        oPlay.style.display = "block";
        oPause.style.display = "none";
    }
    myMusic.src = "mp3/" +musicList[n];
    myMusic.play();
});


在頁面中顯示當前播放的歌曲名:

//用於顯示當前播放的歌曲名
myMusic.addEventListener("canplay", function () {
    oMusicTitle.innerHTML = musicList[n];
});

canplay事件:指可以播放。也就是在歌曲播放過程的事件。


JS部分全部代碼:

window.onload = function () {
    var myMusic = document.getElementById("myMusic");
    var oPlay = document.getElementsByClassName("play")[0];
    var oPause = document.getElementsByClassName("pause")[0];
    var oProgress = document.getElementsByClassName("progress")[0];
    var oBar = document.getElementsByClassName("bar")[0];
    var oBg = document.getElementsByClassName("bg")[0];
    var oSinger = document.getElementsByClassName("singer")[0];
    var oPrve = document.getElementsByClassName("prev")[0];
    var oNext = document.getElementsByClassName("next")[0];
    var oMusicTitle = document.getElementsByClassName("musicTitle")[0];
     
    
    /* 點擊實現播放功能 */
    oPlay.onclick = function () {   
        myMusic.play();
        oPause.style.display = "block";
        this.style.display = "none";
        oSinger.className = "singer rotate";
    };
    
    /* 點擊實現暫停功能 */
    oPause.onclick = function () {
        myMusic.pause();
        oPlay.style.display = "block";
        this.style.display = "none";
        oSinger.className = "singer";
    };
    
    /* 進度條功能 */
    var w = oProgress.offsetWidth - oBar.offsetWidth; //計算小滑塊可移動的範圍
    myMusic.addEventListener("timeupdate", function () {
        var s = this.currentTime/this.duration; //當前時間/總時間
        oBar.style.transform = "translate("+s*w +"px, -0.15rem)"; //滑塊隨音樂移動
        oBg.style.width = s*w + "px";
    });
    
    
    
    //觸屏事件拖拽進度條
    var x = 0, l = 0, _left = 0;
    oBar.addEventListener("touchstart", function (e) {
        var x = e.changedTouches[0].pageX; //獲取手指按下去的位置
        document.addEventListener("touchmove", move);
        document.addEventListener("touchend", function () {
            l = _left;
        });
    });
    
    function move(e) {
        var x1 = e.changedTouches[0].pageX;
        var _left = x1 -x + l;
        if (_left < 0) {
            _left = 0;
        } else if (_left > w) {
            _left = w;
        }
        oBar.style.transform = "translate("+_left+"px, -0.15rem)";
        oBg.style.width = _left + "px";
        myMusic.currentTime = _left/w*myMusic.duration;
    }
    
    
    //用數組保存音樂
    var musicList = ["兒童歌曲-捉泥鰍.mp3", "李茂山-遲來的愛.mp3", "宋祖英-好日子.mp3",
    "譚嘉儀-小幸運.mp3", "王菲-愛不可及.mp3"];
    var n = 0; //索引
    
    //頁面加載完成後顯示的歌曲
    oMusicTitle.innerHTML = musicList[n];
    myMusic.src = "mp3/"+ musicList[n];
    
    if (myMusic.currentTime > myMusic.duration) {
        n ++;
        myMusic.src = "mp3/"+ musicList[n];
        myMusic.play();
    }
    
    //上一曲功能
    oPrve.onclick = function () {
        n --;
        if (n < 0) {
            n = 4;
        }
        myMusic.src = "mp3/"+ musicList[n];
        myMusic.play();
        oSinger.className = "singer rotate";
        oPause.style.display = "block";
        oPlay.style.display = "none";
    };
    
    //下一曲功能
    oNext.onclick = function () {
        n++;
        if (n > 4) {
            n = 0;
        }
        myMusic.src = "mp3/" +musicList[n];
        myMusic.play();
        oSinger.className = "singer rotate";
        oPause.style.display = "block";
        oPlay.style.display = "none";
    };
    
    //自動播放下一曲
    myMusic.addEventListener("ended", function (e){
        n ++;
        if (n > 4) {
            myMusic.pause();
            myMusic.src = "";
            oSinger.className = "singer";
            oBg.style.width = 0;
            oBar.style.transform = "translate("+0+"px, -0.15rem)";
            oPlay.style.display = "block";
            oPause.style.display = "none";
        }
        myMusic.src = "mp3/" +musicList[n];
        myMusic.play();
    });
    
    //用於顯示當前播放的歌曲名
    myMusic.addEventListener("canplay", function () {
        oMusicTitle.innerHTML = musicList[n];
    });
};


這裏使用"window.onload"事件是爲了當加載完成後,播放器顯示歌曲列表的第一首歌曲。這樣無需在HTML中添加歌曲了。



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