html+原生js制作一个简易音乐播放器

简介: html+原生js制作一个简易音乐播放器

纯前端语言编写音乐播放器


app效果图:




播放器实现的功能


  • 列表点击播放
  • 自动循环播放
  • 上一首
  • 下一首
  • 暂停、继续
  • 随机播放
  • 单曲循环


本文的音乐资源


http://www.softeem.xin:8888/public/musicData/musicData.json

下面这些按钮是导入了字体图标库font-awesome 4.7.0 ,需要自己引入



html代码


<html>
    <head>
        <!-- 对于需要在移动终端中显示的页面需要添加如下配置 -->
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <meta charset="utf-8" />
        <title>爱音乐</title>
        <!-- 引入核心样式文件 -->
        <link rel="stylesheet" href="./css/index.css">
        <!-- 导入字体图标库font-awesome 4.7.0 -->
        <link rel="stylesheet" href="./res/font-awesome-4.7.0/css/font-awesome.css">
    </head>
    <body>
        <!-- emmet - PHP -->
        <div id="app" class="verticle">
            <!-- header区域布局 -->
            <div class="header center">
                <img src="./img/20201124032511.png" alt="">
            </div>
            <!-- body区域布局 -->
            <div class="body verticle">
                <!-- 当前播放的歌曲名 -->
                <div class="playing_music_name center">爱音乐</div>
                <!-- 唱片结构 -->
                <div class="cover-disc center ">
                    <img src="img/img01.jpg" alt="">
                </div>
                <div class="playing_music_name text center">快在列表中选择一首歌吧</div>
            </div>
            <!-- footer区域布局 -->
            <div class="footer verticle">
                <!-- 进度条触摸区域 -->
                <div class="progress-box">
                    <!-- 进度条背景 -->
                    <div class="progress-bg">
                        <!-- 实际播放进度 -->
                        <div class="progress">
                            <!-- 滑块 -->
                            <div class="thumb"></div>
                        </div>
                    </div>
                </div>
                <!-- 播放时间显示区域 -->
                <div class="time horizontal">
                    <div class="time-now"></div>
                    <div class="time-total"></div>
                </div>
                <!-- 歌曲播放控制区域 -->
                <div class="controls horizontal">
                    <button class="btn-loop-type">
                        <i class="fa fa-random"></i>
                    </button>
                    <button class="btn-prev">
                        <i class="fa fa-fast-backward fa-2x"></i>
                    </button>
                    <button class="btn-play-pause">
                        <i class="fa fa-pause-circle-o fa-4x"></i>
                    </button>
                    <button class="btn-next">
                        <i class="fa fa-fast-forward fa-2x"></i>
                    </button>
                    <button class="btn-music-list">
                        <i class="fa fa-list-ul"></i>
                    </button>
                </div>
            </div>
        </div>
        <!-- 悬浮框歌曲列表层,默认隐藏 -->
        <div class="music-list-container">
            <!-- 关闭按钮 -->
            <button class="btn-close">
                <i class="fa fa-times-circle-o fa-2x "></i>
            </button>
            <div class="music-list">
                <ul>
                    <li>孤勇者01</li>
                    <li>孤勇者02</li>
                    <li>孤勇者03</li>
                </ul>
            </div>
        </div>
        <!-- 引入js脚本 -->
        <script src="./js/index.js"></script>
    </body>
</html>


css代码


*{
    margin:0;
    padding: 0;
}
/* 弹性布局(垂直) */
.verticle{
    display: flex;
    flex-direction: column;
}
/* 弹性布局(水平) */
.horizontal{
    display: flex;
    flex-direction: row;
}
#app{
    width:100vw;
    height:100vh;
    background:linear-gradient(135deg, #ed2f6d, #85bdd8);
}
/* header区域样式 */
.header{
    flex:1;
}
.header>img{
    height: 3rem; 
    /* 1rex=16px */
}
.center{
    display:flex;
    align-items: center;
    justify-content: center;
}
/* body区域样式 */
.body{
    flex:8;
    background: #eee;
}
.playing_music_name{
    flex:1;
    font-size: 1.2rem;
    letter-spacing: 2px;
    color: #3498db;
}
.cover-disc{
    flex:6;
    background: url('../img/disc.png') no-repeat center center;
    /* 动画 */
    animation: cycler 5s infinite linear;
    animation-play-state:paused;
}
/* 执行动画 */
.playing{
    animation-play-state: running;
}
.cover-disc>img{
    width: 50%;
    border-radius: 50%;
}
/* footer区域样式 */
.footer{
    flex:2;
}
.progress-box{
    flex:1;
}
.progress-bg{
    height: 2px;
    background: #fff;
}
.progress{
    /* 子绝父相 */
    position: relative; 
    height: 100%;
    width: 0%;
    background: #ff6700;
}
.thumb{
    position: absolute;
    right: -5px;
    top: -6px;
    width: 6px;
    height: 6px;
    border:4px solid #fff;
    text-align: center;
    background: #ff6700;
    border-radius: 50%;
    box-shadow: 0 0 20px #ff6700;
}
.time{
    flex:1;
}
.time>div{
    padding:0 5px;
    flex:1;
    color:#fff;
}
.time-total{
    text-align: right;
}
.controls{
    flex:5;
}
.controls>button{
    background: transparent;
    border: 0;
    color: #fff;
}
.btn-loop-type,
.btn-music-list{
    flex: 1;
}
.btn-prev,
.btn-next{
    flex: 2;
}
.btn-play-pause{
    flex: 3;
}
/* 自定义旋转动画 */
@keyframes cycler{
    from{
        transform:rotate(0deg);
    }
    to{
        transform:rotate(360deg);
    }
}
/*歌曲列表悬浮层样式*/
.music-list-container{
    position: absolute;
    left:0;
    right:0;
    bottom:0;
    top:10rem;
    z-index: 99999; /*层叠*/
    background: rgba(0,0,0,0.5);
    display: none; /*初始隐藏悬浮层*/
    overflow-y: scroll;/*纵轴方向如果内容溢出,则滚动显示*/
}
.btn-close{
    position: fixed;
    top:10.25rem;
    right: 0.25rem;
    z-index: 1;
    color:#fff; /*设置字体图标颜色*/
    border:0; /*去除按钮边框*/
    background: transparent;/*去除按钮的背景色*/
}
.music-list{
    padding:0.5rem;
    color:#eee;
    font-size: 1.2rem;
}
.music-list li{
    padding:0.8rem 0;
}
.music-list li:hover,
.playing-holder{
    color:#ff6700;
    background: rgba(255,255,255,0.5);
}
.music-list li:not(:last-child){
    /* 设置选中元素的下边框 */
    border-bottom: 1px solid rgba(255,255,255,0.5);
}


js代码


//自调用函数
(function() {
    //歌曲列表api接口
    const Base_url = 'http://www.softeem.xin:8888/public/musicData/'
    const Music_url = Base_url + 'musicData.json'
    //声明媒体播放器对象
    var player = document.createElement('audio');
    //定义数组对象存储所有的歌曲
    var musics = [];
    //记录当前播放的歌曲索引
    var currentIndex = 0;
    //播放器的当前进度和总进度
    var now = 0;
    var total = 0;
    //歌曲播放状态
    var isPlay = false;
    //歌曲状态 0-列表 1-随机 2-单曲循环
    var loopType = 0;
    // 实现点击歌曲列表的显示
    document.querySelector('.btn-music-list').onclick = function() {
        document.querySelector('.music-list-container').style.display = 'block'
    }
    document.querySelector('.btn-close').onclick = function() {
        document.querySelector('.music-list-container').style.display = 'none'
    }
    //请求远程服务器,获取服务端提供的歌曲信息
    //创建XMLHttoRequest对象(java中与服务端交互对象)
    var xhr = new XMLHttpRequest();
    //打开连接
    xhr.open('GET', Music_url);
    //发送请求
    xhr.send(null);
    //当准备状态发生变化时执行回调
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var data = xhr.responseText;
            //将json字符串解析为js对象
            musics = JSON.parse(data);
            var html = '';
            //i是索引,m是歌曲
            musics.forEach((m, i) => {
                //每读取到一条数据创建一个dom节点
                html += `<li data-index="${i}" >${m.musicName}</li>`;
            })
            document.querySelector('.music-list>ul').innerHTML = html;
        }
    }
    //为列表项绑定点击事件,播放音乐(事件委托)
    document.querySelector('.music-list>ul').onclick = function(e) {
        document.querySelectorAll('.music-list li')[currentIndex].className = '';
        //获取真实被点击的目标元素
        currentIndex = e.target.dataset.index;
        var m = musics[currentIndex];
        var url = Base_url + m.musicPath;
        player.src = url;
        document.querySelector('.text').innerText  = "";
        startPlay(m);
    }
    function startPlay(m) {
        //播放
        var music_play = player.play();
        if (music_play) {
            music_play.then(() => {
                // 音乐加载成功
                isPlay = true;
                // 播放需要耗时
                setTimeout(() => {
                    // 后续操作
                    console.log("done.");
                }, total.duration * 1000); // total.duration 为音乐的时长,单位为秒
            }).catch((e) => {
                // 加载失败
            })
        }
        //显示歌曲名
        document.querySelector('.playing_music_name').innerText = m.musicName;
        //唱片图片更新
        document.querySelector('.cover-disc>img').src = Base_url + m.picPath;
        //唱片旋转
        document.querySelector('.cover-disc').className = 'cover-disc center playing';
        //设置正在播放的歌曲的高亮
        document.querySelectorAll('.music-list li')[currentIndex].className = 'playing-holder';
    }
    //为播放器对象绑定歌曲的第一帧加载完成事件
    player.addEventListener('loadeddata', function() {
        //获取歌曲总时长
        total = player.duration;
        document.querySelector('.time-total').innerText = formaTime(total);
    })
    player.addEventListener('timeupdate', function() {
        now = player.currentTime;
        //计算进度条
        var progress = now / total * 100 + '%';
        document.querySelector('.progress').style.width = progress;
        document.querySelector('.time-now').innerText = formaTime(now);
    })
    function formaTime(time) {
        //以毫秒为基础创建日期对象
        time = new Date(time * 1000);
        var m = time.getMinutes();
        var s = time.getSeconds();
        m = m < 10 ? '0' + m : m;
        s = s < 10 ? '0' + s : s;
        return m + ':' + s;
    }
    //播放暂停按钮绑定单击事件
    document.querySelector('.btn-play-pause').onclick = function() {
        if (isPlay) {
            //暂停
            player.pause();
            //唱片停止旋转
            document.querySelector('.cover-disc').className = 'cover-disc center';
            //更改按钮图标
            this.innerHTML = '<i class="fa fa-play-circle-o fa-4x"></i>';
            isPlay = false;
        } else {
            startPlay(musics[currentIndex]);
            this.innerHTML = '<i class="fa fa-pause-circle-o fa-4x"></i>';
        }
    }
    document.querySelector('.btn-loop-type').onclick = function() {
        //loopType始终在0-2之间
        loopType = ++loopType % 3;
        var t="";
        if (loopType == 0) {
            //列表
            t="列表循环";
            this.innerHTML = '<i class="fa fa-list-ol"></i>';
        } else if (loopType == 1) {
            //随机
            t="随机循环";
            this.innerHTML = '<i class="fa fa-random"></i>';
        } else {
            //单曲
            t="单曲循环";
            this.innerHTML = '<i class="fa fa-repeat"></i>';
        }
        document.querySelector('.text').innerText  = t;
    }
    function nextMusic() {
        if (currentIndex != -1) {
            document.querySelectorAll('.music-list li')[currentIndex].className = '';
        }
        if (loopType == 0) {
            //列表
            currentIndex++;
            if (currentIndex >= musics.length) currentIndex = 0;
        } else if (loopType == 1) {
            //随机
            currentIndex = parseInt(Math.random() * musics.length);
        } //由于单曲循环无需修改索引,因此不作处理
        player.src = Base_url + musics[currentIndex].musicPath;
        startPlay(musics[currentIndex])
    }
    function prevMusic() {
        if (currentIndex != -1) {
            document.querySelectorAll('.music-list li')[currentIndex].className = '';
        }
        if (loopType == 0) {
            //列表循环
            currentIndex--;
            if (currentIndex <= 0) currentIndex = musics.length - 1;
        } else if (loopType == 1) {
            //随机循环
            currentIndex = parseInt(Math.random() * musics.length);
        }
        player.src = Base_url + musics[currentIndex].musicPath;
        startPlay(musics[currentIndex])
    }
    //滑动进度条
    document.querySelector('.progress-box').onclick = function(e) {
        var n=(e.clientX/document.body.clientWidth)*100+'%';
        document.querySelector('.progress').style.width  = n;
        player.currentTime=(e.clientX/document.body.clientWidth)*total;
    }
    document.querySelector('.btn-prev').onclick = prevMusic;
    document.querySelector('.btn-next').onclick = nextMusic;
    //歌曲播放完自动下一首
    player.addEventListener('ended', nextMusic);
})();
相关文章
|
15天前
|
Web App开发 移动开发 HTML5
html5 + Three.js 3D风雪封印在棱镜中的梅花鹿动效源码
html5 + Three.js 3D风雪封印在棱镜中的梅花鹿动效源码。画面中心是悬浮于空的梅花鹿,其四周由白色线段组成了一个6边形将中心的梅花鹿包裹其中。四周漂浮的白雪随着多边形的转动而同步旋转。建议使用支持HTML5与css3效果较好的火狐(Firefox)或谷歌(Chrome)等浏览器预览本源码。
51 2
|
1月前
|
前端开发 JavaScript
用HTML CSS JS打造企业级官网 —— 源码直接可用
必看!用HTML+CSS+JS打造企业级官网-源码直接可用,文章代码仅用于学习,禁止用于商业
130 1
|
1月前
|
前端开发 JavaScript 安全
HTML+CSS+JS密码灯登录表单
通过结合使用HTML、CSS和JavaScript,我们创建了一个带有密码强度指示器的登录表单。这不仅提高了用户体验,还帮助用户创建更安全的密码。希望本文的详细介绍和代码示例能帮助您在实际项目中实现类似功能,提升网站的安全性和用户友好性。
47 3
|
1月前
|
JavaScript
JS鼠标框选并删除HTML源码
这是一个js鼠标框选效果,可实现鼠标右击出现框选效果的功能。右击鼠标可拖拽框选元素,向下拖拽可实现删除效果,简单实用,欢迎下载
42 4
|
1月前
|
移动开发 HTML5
html5+three.js公路开车小游戏源码
html5公路开车小游戏是一款html5基于three.js制作的汽车开车小游戏源代码,在公路上开车网页小游戏源代码。
59 0
html5+three.js公路开车小游戏源码
|
JavaScript 前端开发
四种常见的提示弹出框(success,warning,error,loading)原生JavaScript和jQuery分别实现
原文:四种常见的提示弹出框(success,warning,error,loading)原生JavaScript和jQuery分别实现  虽然说现在官方的自带插件已经有很多了,但是有时候往往不能满足我们的需求,下面我简单介绍一些 常见的四种提示弹出框(success,loading,error,w...
2317 0
|
1月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
25 1
JavaScript中的原型 保姆级文章一文搞懂
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
104 2
|
27天前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
17 0
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
147 4