原生H5+JS+CSS实现音乐播放器(上下一首,随机单曲循环播放,进度条,播放列表) 您所在的位置:网站首页 音乐播放标志符号循环怎么设置 原生H5+JS+CSS实现音乐播放器(上下一首,随机单曲循环播放,进度条,播放列表)

原生H5+JS+CSS实现音乐播放器(上下一首,随机单曲循环播放,进度条,播放列表)

2024-07-09 16:14| 来源: 网络整理| 查看: 265

学了前端小半个月了,今天自己动手写一个音乐播放器实现的功能有 播放列表 ,随机单曲循环播放,上下一首,暂停和开始,静音,音量增加减少,进度条(收藏功能暂未实现,为了排版好看添加的,后续补充收藏等功能)。

话不多说,下面进入到h5页面的代码

 h5页面:

Title 00:00 00:00

 下面CSS的页面

2023.3.25更新 #listALL   .firstMusic 样式 

{ padding: 0; margin: 0; box-sizing: border-box; } html,body{ height: 100%; background-size:cover; backdrop-filter: blur(100px); } @keyframes totate { 0% { transform: rotateZ(0); } 50% { transform: rotateZ(180deg); } 100% { transform: rotateZ(360deg); } } .main { justify-content: space-between; display: flex; overflow: hidden; } #musicImg { margin: 20px 650px; animation: totate 30s linear infinite; border-radius: 50%; background-image: url("../img/bandaotiehe.jpg"); margin-bottom: 100px; animation-play-state: paused; } /*#musicImg:hover { animation-play-state: paused; }*/ .item{ } .firstMusic{ color: red; } #listALL{ position: absolute; width: 350px; display:none; background-color: #363636; top: 200px; opacity: 0.6; } .li{ color: whitesmoke; height: 35px; font-size: 25px; } div { cursor: pointer; /* float: left; */ margin: 10px auto; text-align: center; } #musicName{ font-size: 40px; margin-bottom: 80px; } #collect{ background: url("../img/icon_collect.png"); width: 40px; height: 40px; background-size: 100% 100%; } #selection{ background: url("../img/xunhuanbofang.png"); width: 40px; height: 40px; background-size: 100% 100%; } #list{ background: url("../img/24gl-playlistMusic.png"); width: 40px; height: 40px; background-size: 100% 100%; } #play{ background: url(../img/bofang.png); width: 40px; height: 40px; background-size: 100% 100%; } #prev{ background: url("../img/shangyishoushangyige.png"); width: 40px; height: 40px; background-size: 100% 100%; } #next{ background: url("../img/xiayigexiayishou.png"); width: 40px; height: 40px; background-size: 100% 100%; } #slince{ background: url("../img/24gl-volumeMiddle.png"); width: 40px; height: 40px; background-size: 100% 100%; } #rise{ background: url("../img/24gl-volumeHigh.png"); width: 40px; height: 40px; background-size: 100% 100%; } #minus{ background: url("../img/24gl-volumeLow.png"); width: 40px; height: 40px; background-size: 100% 100%; } #cTime { /*float: left;*/ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; font-size: 18px; width: 20px; } #tTime { /*float: right;*/ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; font-size: 18px; width:300px; } #progress { margin-left: 10px; margin-right: 10px; /*background-color: cyan;*/ } #meter { width: 720px; height: 18px; /*background: azure; margin-bottom: ;*/ }

JS的DOM创建

var audioDOM = document.getElementById("audio"); var collectDOM = document.getElementById("collect"); var selectionDOM = document.getElementById("selection"); var prevDOM = document.getElementById("prev"); var playDOM = document.getElementById("play"); var nextDOM = document.getElementById("next"); var slinceDOM = document.getElementById("slince"); var listDOM = document.getElementById("list"); var listALLDOM = document.getElementById("listALL"); var musicNameDOM = document.getElementById("musicName") var musicImgDOM = document.getElementById("musicImg") var tTimeDOM = document.getElementById("tTime") var cTimeDOM = document.getElementById("cTime") var meterDOM = document.getElementById("meter") var bodyDOM = document.getElementById("body") var riseDOM = document.getElementById("rise") var minusDOM = document.getElementById("minus")

音乐列表

var songs = [ { name: "周杰伦 - 半岛铁盒", photo: "../img/bandaotiehe.jpg" }, { name: "周杰伦 - 外婆", photo: "../img/waipo.jpg" }, { name: "周杰伦 - 完美主义", photo: "../img/wanmeizhuyi.jpg" }, { name: "周杰伦 - 威廉古堡", photo: "../img/weiliangubao.jpg" }, { name: "周杰伦 - 蜗牛", photo: "../img/woniu.jpg" }, { name: "wake", photo: "../img/wake.jpg" }, { name: "ceshi", photo: "../img/ceshi.png" } ] musicNameDOM.innerText = songs[0].name musicImgDOM.src = songs[0].photo

切换歌曲(上一首下一首)

首先创建两个变量记录当前歌曲的索引和歌曲的数量,给nextDOM创建事件监听,当点击触发 next(),因为我写了一个随机播放的功能,所以要考虑如果当前是随机播放的模式,,点击下一首也要随机播放,所以要给userChangeSong传一个随机数,用Math方法。

2023.3.25更新 添加每一次手动切换歌曲时重置进度条已加载的长度。

2023.3.28更新 将next方法里的给changeSong传值改为1.1 因为这样的话在点击列表播放里的索引位置为1的歌曲就不会冲突。

Math.floor(Math.random() * songs.length) var currentSongIndex = 0; var songsListLength = songs.length; audioDOM.src = './mp3/' + songs[currentSongIndex].name + '.mp3' nextDOM.addEventListener('click', next) function next() { meterDOM.setAttribute('value',0) if (selectionDOM.title == "随机播放") { changeSong(Math.floor(Math.random() * songs.length)) } else { changeSong(1.1) } } prevDOM.addEventListener('click', prev) function prev() { meterDOM.setAttribute('value',0) if (selectionDOM.title == "随机播放") { changeSong(Math.floor(Math.random() * songs.length)) } else { changeSong(-1.1) } }

方法userChangeSong的代码 2023.3.28废除 因为跟changeSong方法重复

function userChangeSong(userNum) { currentSongIndex = userNum; audioDOM.src = './mp3/' + songs[currentSongIndex].name + '.mp3'; audioDOM.play() for (let j = 0; j < selectDOM.children.length; j++) { selectDOM.children[j].classList.remove('firstMusic'); } selectDOM.children[currentSongIndex].classList.add('firstMusic'); playDOM.style.backgroundImage = 'url("./img/zanting.png")'; musicNameDOM.innerText = songs[currentSongIndex].name; musicImgDOM.src = songs[currentSongIndex].photo; bodyDOM.background = ".img/" + songs[currentSongIndex].photo; musicImgDOM.style.animationPlayState = "running" }

changeSong的方法 

2023.3.28 更新现在全局使用changSong方法 上面的userChangeSong废弃。

将从next和prev得到1.1和-1.1转换为整数类型,以防出错。

function changeSong(num) { if (num == 1.1 || num == -1.1){ num = parseInt(num); currentSongIndex = (currentSongIndex + num + songsListLength) % songsListLength; }else { currentSongIndex = num; } audioDOM.src = './mp3/' + songs[currentSongIndex].name + '.mp3'; for (let j = 0; j < selectDOM.children.length; j++) { selectDOM.children[j].classList.remove('nowMusic'); } selectDOM.children[currentSongIndex].classList.add('nowMusic'); audioDOM.play() playDOM.style.backgroundImage = 'url("./img/zanting.png")'; musicNameDOM.innerText = songs[currentSongIndex].name; musicImgDOM.src = songs[currentSongIndex].photo; bodyDOM.background = ".img/" + songs[currentSongIndex].photo; musicImgDOM.style.animationPlayState = "running" }

切换播放方式(单曲循环随机播放),具体实现下文我会通过进度条的判断来实现音乐循环随机播放。

selectionDOM.addEventListener('click', playModeSelection) function playModeSelection() { if (selectionDOM.title == "循环播放") { selectionDOM.style.backgroundImage = 'url("../img/danquxunhuan.png")' selectionDOM.title = "单曲播放" audioDOM.loop = true; } else if (selectionDOM.title == "单曲播放") { selectionDOM.style.backgroundImage = 'url("../img/suijibofang.png")' selectionDOM.title = "随机播放"; audioDOM.loop = false; } else if (selectionDOM.title == "随机播放") { selectionDOM.style.backgroundImage = 'url("../img/xunhuanbofang.png")' selectionDOM.title = "循环播放"; audioDOM.loop = false; } }

进度条的实现,点击进度条会跳转到指定的时间。给进度条一个计时器放到function play()里(在下文播放暂停的代码区),每隔一秒判断一次当前歌曲是否播放结束。

meterDOM.onclick = setProgress; function setProgress(e) { var offsetLeft = (e.clientX - meterDOM.offsetLeft) / meterDOM.offsetWidth; audioDOM.currentTime = offsetLeft * audioDOM.duration; meterDOM.setAttribute('value', offsetLeft * 100) } function showProgress() { if (audioDOM.ended && selectionDOM.title == "随机播放") { console.log(Math.floor(Math.random() * songs.length)) changeSong(Math.floor(Math.random() * songs.length)) } else if (audioDOM.ended && selectionDOM.title == "循环播放") { changeSong(1) } meterDOM.setAttribute('value', audioDOM.currentTime / audioDOM.duration * 100); }

音乐的时间。

/*歌曲时间 loadedmetadata: 当指定的音频/视频的元数据已加载时,会发生 loadedmetadata 事件。 音频/视频的元数据包括:时长、尺寸(仅视频)以及文本轨道。 timeupdate : 事件在音频/视频(audio/video)的播放位置发生改变时触发。 duration: 属性以秒或毫秒为单位指定过渡动画所需的时间。默认值为 0s */ audioDOM.addEventListener("loadedmetadata", function (event) { if (audioDOM.duration % 60 < 10) { tTimeDOM.innerHTML = parseInt(audioDOM.duration / 60) + ":0" + parseInt(audioDOM.duration % 60) } else { tTimeDOM.innerHTML = parseInt(audioDOM.duration / 60) + ":" + parseInt(audioDOM.duration % 60) } }); audioDOM.addEventListener("timeupdate", function (event) { if (audioDOM.currentTime < 10) { cTimeDOM.innerHTML = "0:0" + Math.floor(audioDOM.currentTime); } else if (audioDOM.currentTime < 60) { cTimeDOM.innerHTML = "0:" + Math.floor(audioDOM.currentTime); } else { var minet = parseInt(audioDOM.currentTime / 60); var sec = audioDOM.currentTime - minet * 60; if (sec < 10) { cTimeDOM.innerHTML = "0" + minet + ":" + "0" + parseInt(sec); } else { cTimeDOM.innerHTML = "0" + minet + ":" + parseInt(sec); } } });

音乐暂停和播放,里面添加了一个计时器用来实现进度实时变化。

/* 暂停 开始*/ var timer = null; playDOM.addEventListener('click', play) function play() { if (audioDOM.paused) { audioDOM.play() timer = setInterval(showProgress, 1000); playDOM.style.backgroundImage = 'url("./img/zanting.png")' playDOM.setAttribute("title", "暂停") musicImgDOM.style.animationPlayState = "running" } else { audioDOM.pause() playDOM.title = "播放" playDOM.style.backgroundImage = 'url("./img/bofang.png")' musicImgDOM.style.animationPlayState = "paused" clearInterval(timer) } }

音乐音量的控制

/* 控制音量大小 */ slinceDOM.addEventListener("click", slince) function slince() { if (slinceDOM.title == "静音") { audioDOM.muted = true slinceDOM.title = "非静音" slinceDOM.style.backgroundImage = 'url("../img/24gl-volumeDisable.png")' } else { audioDOM.muted = false slinceDOM.title = '静音' slinceDOM.style.backgroundImage = 'url("../img/24gl-volumeMiddle.png")' } } /*每点击一下,增加10%,如果超过最大就为1,超过最小就为0*/ riseDOM.addEventListener('click', function () { changeVol(0.1) }) minusDOM.addEventListener('click', function () { changeVol(-0.1) }) function changeVol(n) { if (audioDOM.volume + n < 0) { audioDOM.volume = 0; } else if (audioDOM.volume + n


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有