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);
})();
相关文章
|
8天前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
46 6
|
22天前
|
XML 前端开发 JavaScript
前端开发进阶:从HTML到React.js
【10月更文挑战第9天】前端开发进阶:从HTML到React.js
|
29天前
|
JavaScript 前端开发
电话号码正则表达式 代码 javascript+html,JS正则表达式判断11位手机号码
电话号码正则表达式 代码 javascript+html,JS正则表达式判断11位手机号码
70 1
|
23天前
|
JavaScript 前端开发
JavaScript 与 HTML 的结合
JavaScript 与 HTML 的结合
14 0
|
29天前
|
机器学习/深度学习 JSON JavaScript
LangChain-21 Text Splitters 内容切分器 支持多种格式 HTML JSON md Code(JS/Py/TS/etc) 进行切分并输出 方便将数据进行结构化后检索
LangChain-21 Text Splitters 内容切分器 支持多种格式 HTML JSON md Code(JS/Py/TS/etc) 进行切分并输出 方便将数据进行结构化后检索
22 0
|
2月前
|
XML 前端开发 JavaScript
Html:CSS介绍
Html:CSS介绍
48 1
|
2月前
|
前端开发
Html:CSS的书写位置
Html:CSS的书写位置
28 0
|
1天前
|
移动开发 前端开发 JavaScript
[HTML、CSS]知识点
本文涵盖前端知识点扩展、HTML标签(如video、input、canvas)、datalist和details标签的使用方法,以及CSS布局技巧(如margin、overflow: hidden和动态height)。文章旨在分享作者的学习经验和实用技巧。
10 1
[HTML、CSS]知识点
|
1月前
|
前端开发 JavaScript 搜索推荐
打造个人博客网站:从零开始的HTML和CSS之旅
【9月更文挑战第32天】在这个数字化的时代,拥有一个个人博客不仅是展示自我的平台,也是技术交流的桥梁。本文将引导初学者理解并实现一个简单的个人博客网站的搭建,涵盖HTML的基础结构、CSS样式的美化技巧以及如何将两者结合来制作一个完整的网页。通过这篇文章,你将学会如何从零开始构建自己的网络空间,并在互联网世界留下你的足迹。