關於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中輸入對應的代碼就相對應按鈕,如:輸入“”就相當於“上一曲按鈕”。
使用這種圖標分三個步驟:使用之前需要下載圖標文件:阿里矢量圖標管網,下載完成後:將裏面的文件保存在一個文件夾裏面,接着:
- 第一步,使用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:音樂的總時間
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)
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中添加歌曲了。