600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 原生H5+JS+CSS实现音乐播放器(上下一首 随机单曲循环播放 进度条 播放列表)

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

时间:2019-10-11 21:24:39

相关推荐

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

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

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

h5页面:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" type="text/css" href="./css/audioCSS.css"></head><body id="body" background="./img/bandaotiehe.jpg"><!--音乐播放图片--><img id="musicImg" src="" title="" width="400px" height="400px"><!--音乐播放名字--><div id="musicName" class="name" id="musicName"></div><div class="item"><ul id="listALL"></ul></div><div class="main" id="main" ><audio id="audio" src=""></audio><div id="collect" title="收藏"></div><div id="list" title="列表"></div><div id="selection" title="循环播放"></div><div id="prev" title="上一首"></div><div id="play" title="播放"></div><div id="next" title="下一首"></div><div id="slince" title="静音"></div><div id="rise" title="加音量"></div><div id="minus" title="减音量"></div></div><br><div class="progress" id="progress"><span class="cTime time" id="cTime">00:00</span> <!-- 当前时间 --><meter value="0" max="100" id="meter" ></meter><!-- 进度条 --><span class="tTime time" id="tTime">00:00</span> <!-- 总的时间 --></div><script src="./js/audio01.js"></script></body></html>

下面CSS的页面

.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].namemusicImgDOM.src = songs[0].photo

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

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

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

.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的代码.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的方法

.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;}}

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

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 = trueslinceDOM.title = "非静音"slinceDOM.style.backgroundImage = 'url("../img/24gl-volumeDisable.png")'} else {audioDOM.muted = falseslinceDOM.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 <= 1.0) {audioDOM.volume = audioDOM.volume + n;} else {audioDOM.volume = 1.0}}

播放列表的动态实现

.3.25更新 添加每一次手动点击列表切换歌曲时重置进度条已加载的长度,添加一些li的样式。

/*播放列表*/listDOM.addEventListener('click', showList)function showList() {if (listDOM.title === "列表") {listALLDOM.style.display = "block";listDOM.title = "关闭播放列表";} else {listALLDOM.style.display = "none";listDOM.title = "列表";}}/*querySelector() 方法返回文档中与指定选择器或选择器组匹配的第一个 Element对象。如果找不到匹配项,则返回null。insertBefore() 方法在现有子节点之前插入子节点。*/var selectDOM = document.querySelector('.item').querySelector('ul');for (var i = 0; i < songs.length; i++) {var li = document.createElement('li');li.innerHTML = songs[i].name;li.title = songs[i].name;li.style.height = "50px"li.style.fontSize = "32px"selectDOM.insertBefore(li, selectDOM.children[i]);}selectDOM.children[0].classList.add('firstMusic');for (var i = 0; i < selectDOM.children.length; i++) {selectDOM.children[i].index = i;selectDOM.children[i].addEventListener('click', function (e) {for (var j = 0; j < selectDOM.children.length; j++) {selectDOM.children[j].classList.remove('firstMusic');}this.classList.add('firstMusic');meterDOM.setAttribute('value',0)changeSong(e.target.index);})}

到这里就结束了,后续添加更多内容。

(第一次写博客,写的不好请谅解)。

完整JS代码

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].namemusicImgDOM.src = songs[0].photo/*收藏*/collectDOM.addEventListener('click', changeCollect)function changeCollect() {if (collectDOM.title == "收藏") {collectDOM.style.backgroundImage = 'url("../img/shoucang.png")';collectDOM.setAttribute("title", "取消收藏");} else {collectDOM.style.backgroundImage = 'url("../img/icon_collect.png")';collectDOM.title = "收藏"}}/*播放方式*/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;}}/*播放 上一首播放 下一首播放*/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)}}/* 暂停 开始*/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(timers)}}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 changeModeMusic() {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)}}*/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);}}});/*进度条*//* 控制音量大小 */slinceDOM.addEventListener("click", slince)function slince() {if (slinceDOM.title == "静音") {audioDOM.muted = trueslinceDOM.title = "非静音"slinceDOM.style.backgroundImage = 'url("../img/24gl-volumeDisable.png")'} else {audioDOM.muted = falseslinceDOM.title = '静音'slinceDOM.style.backgroundImage = 'url("../img/24gl-volumeMiddle.png")'}}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 <= 1.0) {audioDOM.volume = audioDOM.volume + n;} else {audioDOM.volume = 1.0}}/*播放列表*/listDOM.addEventListener('click', showList)function showList() {if (listDOM.title === "列表") {listALLDOM.style.display = "block";listDOM.title = "关闭播放列表";} else {listALLDOM.style.display = "none";listDOM.title = "列表";}}/*querySelector() 方法返回文档中与指定选择器或选择器组匹配的第一个 Element对象。如果找不到匹配项,则返回null。insertBefore() 方法在现有子节点之前插入子节点。*/var selectDOM = document.querySelector('.item').querySelector('ul');var li1 = document.createElement('li');for (var i = 0; i < songs.length; i++) {var li = document.createElement('li');li.innerHTML = songs[i].name;li.title = songs[i].name;li.style.height = "50px"li.style.fontSize = "32px"selectDOM.insertBefore(li, selectDOM.children[i]);}selectDOM.children[0].classList.add('nowMusic');for (var i = 0; i < selectDOM.children.length; i++) {selectDOM.children[i].index = i;selectDOM.children[i].addEventListener('click', function (e) {/*可写可不写???*//* for (var j = 0; j < selectDOM.children.length; j++) {selectDOM.children[j].classList.remove('nowMusic');}*/this.classList.add('nowMusic');meterDOM.setAttribute('value',0)console.log(e.target.index)changeSong(e.target.index);playDOM.title = "暂停";})}/*切换歌曲*/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"}/*function changeSong(userNum) {if (userNum == 1.0 || userNum == -1.0){currentSongIndex = (currentSongIndex + num + songsListLength) % songsListLength;}else {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('nowMusic');}selectDOM.children[currentSongIndex].classList.add('nowMusic');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"}*/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。