html网页版音乐播放器

利用html+css+js 实现网页版音乐播放,支持歌词预览,歌曲上一曲下一曲暂停顺序播放循环播放等功能

先上效果图:

歌曲部分:

音乐路径为拼接指定路径下的音乐文件url,无需用户手动选取文件路径

歌词部分:

通过ajax获取歌词lyric文本,js解析每句歌词的播放时间和内容

html代码:


    <div id="main-section">
            <div id="main-section-1">
              <div class="title-style-1">音乐专区</div>
              <div id="articleContent">
                <div id="typeA" class="animateBorder">
                  <div id="titleA" class="titleType">流行音乐</div>
                  <ul class="ulSection">
                    <li class="liSection">
                      <span class="musicTitle">1.爱在日出前</span>
                      <div id="favMusic" class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">2.醉千年</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">3.晚风作酒</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">4.醒不来的梦</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">5.她的眼睛会唱歌</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">6.秋殇别恋</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">7.半壶纱</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">8.连借口都没有</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">9.百花香</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">10.很任性</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                  </ul>
                </div>
     
                <div id="typeB" class="animateBorder">
                  <div id="titleB" class="titleType">经典老歌</div>
                  <ul class="ulSection">
                    <li class="liSection">
                      <span class="musicTitle">1.星月神话</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">2.风度</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">3.暗涌</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">4.爱的故事上集</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">5.吴哥窟</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">6.谁在意我留下的泪</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">7.恋人心</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">8.夜曲</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">9.十一年</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">10.断桥残雪</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                  </ul>
                </div>
     
                <div id="typeC" class="animateBorder">
                  <div id="titleC" class="titleType">其它歌曲</div>
                  <ul class="ulSection">
                    <li class="liSection">
                      <span class="musicTitle">1.想起</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">2.你是风</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">3.乌兰巴托的夜</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">4.The Tower</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">5.家乡</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">6.情非虚构</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">7.我是不是该安静的走开</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">8.曾经心痛</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">9.潮湿的心</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                    <li class="liSection">
                      <span class="musicTitle">10.余情未了</span>
                      <div class="musicStatus" onclick="change(this)"></div>
                    </li>
                  </ul>
                </div>
              </div>
            </div>

JS代码:


      let sectionD1 = document.getElementById("main-section-1");
          let lyricTip = document.getElementById("lyricTip");
          let lyricDisplay = document.getElementById("lyricDisplay");
          let lyricTitle = document.getElementById("lyricTitle");
          let favMusic = document.getElementById("favMusic");
          let progressDiv = document.getElementById("progressDiv");
          let lyricUl = document.getElementById("lyricUl");
          let rollTDiv = document.getElementById("rollTime"); // 实时播放时间Div
          let totalTDiv = document.getElementById("totalTime"); // 总时长时间Div
          let progressBar = document.getElementById("progressBar"); // 歌曲实时进度条
          let progressAni = document.getElementById("progressAni");
          let totalProgress = document.getElementById("totalProgress"); // 歌曲总进度条
          let playType = document.getElementById("playType"); // 播放方式
     
          let isPlay = false,
            lyricF,
            lines;
          let playTypeNum = 1,
            songID,
            typeNum,
            nowMusic; //控制列表和单曲循环
          let patternType1 = /\[(\d{2}:\d{2}).\d{2}\](.+)/,
            patternType2 = /\[(\d{2}:\d{2}).\d{2}\](.+)/g;
          let linesFadeArr = [],
            linesArr = [],
            timeArr = [],
            lyricArr = []; //歌词处理数字
     
          //进度条宽度自动布局
          totalProgress.style.width = progressDiv.clientWidth + "px";
          window.addEventListener("resize", function () {
            sectionD1.style.width = "600px";
            totalProgress.style.width = progressDiv.clientWidth + "px";
          });
     
          let audio = new Audio();
          audio.volume = 0.8;
          change(favMusic);
     
          function change(t) {
            nowMusic = t;
            linesFadeArr = [];
            linesArr = [];
            timeArr = [];
            lyricArr = [];
     
            let musicNum = document.querySelectorAll(".musicStatus");
     
            typeNum = t.parentNode.parentNode.parentNode.children[1].getElementsByTagName("li").length;
     
            for (i = 0; i < musicNum.length; i++) {
              musicNum[i].style.backgroundImage = "url(./music/play.png)";
            }
     
            let context = t.parentNode.children[0].innerHTML.replace(/\n/g, "");
            songID = context.replace(/\D/g, "");
     
            let type = t.parentNode.parentNode.parentNode.id.substr(4, 4);
            let musicSrc = "./music/music" + type + "/" + type + "_" + songID + ".mp3";
     
            let lyricSrc = "./music/music" + type + "/" + type + "_" + songID + ".lrc";
     
            audio.src = musicSrc;
            lyricTitle.innerHTML = context.replace(songID, "").replace(".", "");
            t.style.backgroundImage = "url(./music/pause.png)";
            startStop.className = "buttons start";
     
            //上一曲
            pre.onclick = function () {
              let currentMusicID = songID - 2;
              if (currentMusicID < 0) {
                currentMusicID = typeNum - 1;
              }
              change(t.parentNode.parentNode.children[currentMusicID].children[1]);
            };
     
            //下一曲
            next.onclick = function () {
              let currentMusicID = songID;
              if (currentMusicID > typeNum - 1) {
                currentMusicID = 0;
              }
              change(t.parentNode.parentNode.children[currentMusicID].children[1]);
            };
     
            //播放或暂停
            startStop.onclick = function () {
              if (audio.paused) {
                // 如果当前音乐是暂停状态,点击按钮,则改为播放状态
                startStop.className = "buttons start"; // 设置播放的class
                audio.play();
                nowMusic.parentNode.parentNode.children[songID - 1].children[1].style.backgroundImage = "url(./music/pause.png)";
              } else {
                // 如果当前音乐是播放状态,点击按钮,则改为暂停状态
                startStop.className = "buttons stop"; // 设置暂停的class
                audio.pause();
                nowMusic.parentNode.parentNode.children[songID - 1].children[1].style.backgroundImage = "url(./music/play.png)";
              }
            };
     
            lyricF = fetchItem(lyricSrc);
            if (lyricF == void 0) {
              lyricF = "抱歉,该歌曲暂未找到歌词";
              lyricTip.innerHTML = "抱歉,该歌曲暂未找到歌词";
              lyricTip.style.color = "rgb(9, 226, 161)";
            } else {
              lyricTip.innerHTML = "";
            }
            lines = lyricF.split("\n");
            lyricUl.style.top = 0 + "px";
     
            //去掉空白行
            for (var i = 0; i < lines.length; i++) {
              if (lines[i].trim() !== "") {
                linesFadeArr.push(lines[i].trim());
              }
            }
     
            //去掉不含时间行或只包含时间行
            for (var i = 0; i < linesFadeArr.length; i++) {
              if (!patternType1.test(linesFadeArr[i]) || (patternType1.test(linesFadeArr[i]) && linesFadeArr[i].length == 10)) {
                linesFadeArr.splice(i, 1);
              }
            }
     
            //歌词格式化后最终歌词数组
            for (var i = 0; i < linesFadeArr.length; i++) {
              if (patternType1.test(linesFadeArr[i])) {
                linesArr.push(linesFadeArr[i]);
              }
            }
     
            //加载歌词
            var lyricText = linesArr.join("\n");
            let tmp = patternType2.exec(lyricText);
     
            while (tmp) {
              timeArr.push(tmp[1]);
              lyricArr.push(tmp[2]);
              tmp = patternType2.exec(lyricText);
            }
     
            let str = "";
     
            lyricArr.forEach((item, index) => {
              str += `<li id="lyricLI" class="${index === 0 ? "active" : ""}" >${item}</li>`;
            });
     
            lyricUl.innerHTML = str;
     
            if (isPlay) {
              audio.play();
            } else {
              audio.pause();
              isPlay = true;
              t.style.backgroundImage = "url(./music/play.png)";
              startStop.className = "buttons stop";
            }
          }
     
          //播放状态处理
          audio.addEventListener("timeupdate", function () {
            var totalTime = audio.duration;
            var currentTime = audio.currentTime;
            if (!isNaN(totalTime)) {
              rollTDiv.textContent = getFormatterDate(currentTime);
              totalTDiv.textContent = getFormatterDate(totalTime);
              var width = Math.floor((currentTime / totalTime) * progressDiv.clientWidth);
              progressBar.setAttribute("style", "width:" + width + "px");
              progressAni.setAttribute("style", "left:" + (width - 2) + "px");
              //当前歌曲播放完毕处理
              if (currentTime == totalTime) {
                let musicStatus = document.querySelectorAll(".musicStatus");
     
                for (i = 0; i < musicStatus.length; i++) {
                  musicStatus[i].style.backgroundImage = "url(./music/play.png)";
                }
                rollTDiv.textContent = "00:00";
                progressBar.setAttribute("style", "width:" + 0 + "px");
                progressAni.setAttribute("style", "left:-2px");
                lyricUl.style.top = 0 + "px";
                startStop.className = "buttons stop";
                if (lyricUl.children[0] != void 0) {
                  lyricUl.children[0].className = "active";
                }
                if (playTypeNum == 1) {
                  let currentMusicID = songID;
                  if (currentMusicID > typeNum - 1) {
                    currentMusicID = 0;
                  }
                  change(nowMusic.parentNode.parentNode.children[currentMusicID].children[1]);
                } else if (playTypeNum == 2) {
                  let currentMusicID = songID - 1;
                  if (currentMusicID > typeNum - 1) {
                    currentMusicID = 0;
                  }
                  change(nowMusic.parentNode.parentNode.children[currentMusicID].children[1]);
                }
              }
            }
     
            //歌词渲染
            const minute = parseInt(currentTime / 60);
            const second = parseInt(currentTime % 60);
            const timeStr = (minute < 10 ? "0" + minute : minute) + ":" + (second < 10 ? "0" + second : second);
     
            const index = timeArr.findIndex((item) => item === timeStr);
     
            if (index !== -1) {
              //从第7句开始向上移动歌词位置
              if (index > 6) {
                lyricUl.style.top = -(index - 5) * 20 + "px";
                lIndex = index;
              }
     
              [...lyricUl.children].forEach((item) => (item.className = ""));
              lyricUl.children[index].className = "active";
            }
          });
     
          //监听进度条点击事件
          totalProgress.addEventListener("click", function (event) {
            updateTime(event.offsetX);
          });
          progressBar.addEventListener("click", function (event) {
            updateTime(event.offsetX);
          });
     
          function updateTime(x) {
            var totalTime = audio.duration;
            var currentTime = audio.currentTime;
            let actualWidt = progressDiv.clientWidth;
            var selectProgress = x / actualWidt;
     
            audio.currentTime = totalTime * selectProgress;
     
            var LWidth = Math.floor(selectProgress * actualWidt);
            progressBar.setAttribute("style", "width:" + LWidth + "px");
            audio.play();
          }
     
          //ajax获取文本对象
          function fetchItem(url) {
            var item;
            $.ajax({
              type: "get",
              url,
              async: false,
              success: function (data) {
                item = data;
              },
            });
            return item;
          }
     
          //时间格式化
          function getFormatterDate(time) {
            var m = parseInt(time / 60); // 分
            var s = parseInt(time % 60); // 秒
            // 补零
            m = m > 9 ? m : "0" + m;
            s = s > 9 ? s : "0" + s;
            return m + ":" + s;
          }
     
          //手动调节音量
          let volumeChange = document.getElementById("volumeChange");
          volumeChange.value = audio.volume * 10;
          volumeChange.onchange = function () {
            var volumeVal = volumeChange.value * 0.1;
            audio.volume = volumeVal;
          };
          let voicIcon = document.getElementById("voicIcon");
          let flag = true;
          volumeChange.style.display = "none";
          voicIcon.onmouseover = function () {
            if (flag) {
              volumeChange.style.display = "";
              flag = false;
            }
          };
          voicIcon.onmouseout = function () {
            setTimeout(function () {
              volumeChange.style.display = "none";
              flag = true;
            }, 3000);
          };
     
          //鼠标放在进度条显示时间
          var insTime = $("#insTime");
          function showTime(x) {
            var totalTime = audio.duration;
            let actualWidt = progressDiv.clientWidth;
            let nowTime = getFormatterDate((x / actualWidt) * totalTime);
            if (nowTime == "0NaN:0NaN") {
              insTime.text("");
            } else {
              insTime.text(nowTime);
              insTime.css({ left: x - 20 }).fadeIn(0);
            }
          }
     
          totalProgress.onmouseover = function (event) {
            showTime(event.offsetX);
          };
          progressBar.onmouseover = function (event) {
            showTime(event.offsetX);
          };
          totalProgress.onmouseout = function (event) {
            insTime.text("");
          };
          progressBar.onmouseout = function (event) {
            insTime.text("");
          };
     
          //播放方式按钮点击事件
          playType.onclick = function () {
            if (playTypeNum == 1) {
              // 当前播放为列表循环,点击切换播放方式时,改为单曲循环
              playTypeNum = 2;
              playType.className = "buttons_dqxh"; // 设置单曲循环的class
            } else {
              // 当前播放为单曲循环,点击切换播放方式时,改为列表循环
              playTypeNum = 1;
              playType.className = "buttons_lbxh"; // 设置列表循环的class
            }
          };

完整代码路径:
https://gitee.com/yueluo9527/web-music-play

主页样例:
http://www.lsummer.cn

posted @   月落沉沉  阅读(466)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示