个人小作品之迷你音乐播放器(移动端)

关于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中添加歌曲了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值