实现上一曲、下一曲
现在,为音乐列表设置切换到上一曲和切换到下一曲的功能;在页面中会用到该功能的部分为上一曲按钮、下一曲按钮、音乐结束时自动切换到下一曲。
在播放列表的每一项中添加 data-index
属性来记录其在播放列表中的顺序,对 <audio>
标签设置 data-index
属性来标记当前为播放列表中的第几首曲目。通过读取 data-index
属性来计算出该播放曲目的顺序,上一首、下一首该播放曲目的顺序。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MusicControl</title>
<style>
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
.control-button {
margin-top: 10px;
margin-left: 20px;
}
.clear-both::after {
content: '';
display: block;
clear: both;
}
.play-control-button {
width: 64px;
height: 64px;
background-image: url(icons.png);
float: left;
margin-right: 10px;
cursor: pointer;
}
.prev {
background-position: 0 0;
}
.next {
background-position: 0 -64px;
}
.play {
background-position: 0 -192px;
}
.pause {
background-position: 0 -128px;
}
.control-bar {
margin-top: 20px;
margin-left: 20px;
}
.controlTime {
float: left;
color: #ccc;
}
.play-control-progress {
position: relative;
margin-left: 8px;
margin-right: 8px;
margin-top: 8px;
float: left;
display: block;
width: 300px;
height: 5px;
background-color: #ccc;
}
.playing-progress {
position: absolute;
display: block;
height: 100%;
width: 0%;
background-color: #2f9842;
}
.playing-bar {
position: absolute;
margin-top: -1.5px;
margin-left: -4px;
width: 8px;
height: 8px;
background-color: #2f9842;
border: 0.5px solid #000;
border-radius: 50%
}
.music-list li {
display: block;
list-style: none;
padding-bottom: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<audio id="music" src="" data-index="0"></audio>
<div class="control-button clear-both">
<div class="play-control-button prev" id="controlOne"></div>
<div class="play-control-button play" id="controlTwo"></div>
<div class="play-control-button next" id="controlThree"></div>
</div>
<div class="control-bar clear-both">
<span class="controlTime" id="nowTime">00:00</span>
<div class="play-control-progress" id="controlProgress">
<div class="playing-progress" id="playingProgress"></div>
<div class="playing-bar" id="playingBar"></div>
</div>
<span class="controlTime" id="endTime">00:00</span>
</div>
<div>
<ul class="music-list clear-both" id="musicList">
</ul>
</div>
<script>
window.onload = function() {
let music = document.getElementById('music');
let controlOne = document.getElementById('controlOne');
let controlTwo = document.getElementById('controlTwo');
let controlThree = document.getElementById('controlThree');
let controlProgress = document.getElementById('controlProgress');
let playingProgress = document.getElementById('playingProgress');
let playingBar = document.getElementById('playingBar');
let nowTime = document.getElementById('nowTime');
let endTime = document.getElementById('endTime');
let musicList = document.getElementById('musicList');
let drag = 0;
let flag = 0;
nowTime.innerText = "00:00";
function getMin(min) {
let res = parseInt(min / 60);
if(res < 10) {
return '0' + res;
} else {
return res + '';
}
}
function getSec(min) {
let res = parseInt(min % 60);
if(res < 10) {
return '0' + res;
} else {
return res + '';
}
}
let timer = '';
let stop = '';
let dragTime = 0;
function musicPlay() {
music.play();
timer = setInterval(() => {
let progressLen = music.currentTime / music.duration * controlProgress.clientWidth;
nowTime.innerText = getMin(music.currentTime) + ":" + getSec(music.currentTime);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
},1000);
}
function musicPause() {
music.pause();
clearInterval(timer);
}
class musicObj {
constructor(name, src, author, time) {
this.name = name;
this.src = src;
this.author = author;
this.time = time;
}
};
let musicNameList = ['MusicOne', 'MusicTwo', 'MusicThree'];
let musicSrcLsit = ['Demo0.mp3', 'Demo1.mp3', 'Demo2.mp3'];
let musicAuthorList = ['AuthorOne', 'AuthorTwo', 'AuthorThree'];
let musicTimeList = ['04:01', '02:00', '03:40'];
let musicListObj = new Array();
for(let i in musicNameList) {
musicListObj[i] = new musicObj(musicNameList[i], musicSrcLsit[i], musicAuthorList[i], musicTimeList[i]);
}
function playPrev() {
let dataIndex = parseInt(music.getAttribute('data-index'));
let prevIndex = (dataIndex - 1) < 0 ? musicListObj.length - 1 : (dataIndex - 1);
musicPause();
music.setAttribute('src', musicListObj[prevIndex].src);
music.setAttribute('data-index', prevIndex);
music.currentTime = 0;
nowTime.innerText = "00:00";
endTime.innerText = musicListObj[prevIndex].time;
controlTwo.className = "play-control-button pause";
playingProgress.style.width = 0 + 'px';
playingBar.style.marginLeft = 0 + 'px';
musicPlay();
}
function playNext() {
let dataIndex = parseInt(music.getAttribute('data-index'));
let nextIndex = (dataIndex + 1) > (musicListObj.length - 1) ? 0 : (dataIndex + 1)
musicPause();
music.setAttribute('src', musicListObj[nextIndex].src);
music.setAttribute('data-index', nextIndex);
music.currentTime = 0;
nowTime.innerText = "00:00";
endTime.innerText = musicListObj[nextIndex].time;
controlTwo.className = "play-control-button pause";
playingProgress.style.width = 0 + 'px';
playingBar.style.marginLeft = 0 + 'px';
musicPlay();
}
for(let i in musicListObj) {
let newNode = document.createElement('li');
newNode.setAttribute('data-src', musicListObj[i].src);
newNode.setAttribute('data-time', musicListObj[i].time);
newNode.setAttribute('data-index', i);
newNode.innerText = musicListObj[i].name + ' - ' + musicListObj[i].author;
musicList.appendChild(newNode);
}
controlTwo.addEventListener('click', () => {
console.log("Click");
if(controlTwo.className == "play-control-button play") {
controlTwo.className = "play-control-button pause";
musicPlay();
} else if (controlTwo.className == "play-control-button pause") {
controlTwo.className = "play-control-button play";
musicPause();
}
});
controlProgress.addEventListener('click', (e) => {
e = e || window.e;
let rate = ((e.clientX - controlProgress.getBoundingClientRect().left) / controlProgress.clientWidth);
let progressLen = e.clientX - controlProgress.getBoundingClientRect().left;
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
let theTime = parseInt(rate * (music.duration))
music.currentTime = theTime;
nowTime.innerText = getMin(theTime) + ":" + getSec(theTime);
console.log(rate);
});
playingBar.addEventListener('mousedown', () => {
console.log('mousedown');
drag = 1;
flag = 1;
clearInterval(timer);
});
document.addEventListener('mouseup', () => {
console.log('mouseup');
drag = 0;
if(flag == 1) {
music.currentTime = dragTime;
timer = setInterval(() => {
let progressLen = music.currentTime / music.duration * controlProgress.clientWidth;
nowTime.innerText = getMin(music.currentTime) + ":" + getSec(music.currentTime);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
},1000);
console.log('reStart');
}
flag = 0;
});
controlProgress.addEventListener('mousemove', (e) => {
e = e || window.e;
if(drag == 1) {
console.log('mousemove');
let progressLen = e.clientX - controlProgress.getBoundingClientRect().left;
let rate = (progressLen / controlProgress.clientWidth);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
let theTime = parseInt(rate * (music.duration));
nowTime.innerText = getMin(theTime) + ":" + getSec(theTime);
dragTime = theTime;
}
});
musicList.addEventListener('click', (e) => {
e = e || window.e;
let musicSrc = e.target.getAttribute('data-src');
let dataIndex = e.target.getAttribute('data-index');
musicPause();
music.setAttribute('src', musicSrc);
music.setAttribute('data-index', dataIndex);
music.currentTime = 0;
endTime.innerText = e.target.getAttribute('data-time');
musicPlay();
e.stopPropagation();
});
controlOne.addEventListener('click', () => {
playPrev();
});
controlThree.addEventListener('click', () => {
playNext();
});
music.addEventListener('ended', () => {
playNext();
});
music.src = musicListObj[0].src;
endTime.innerText = musicListObj[0].time;
}
</script>
</body>
</html>
为防止因先使用后定义而造成的变量提升,将代码整理为定义在前,操作在后的格式。
播放歌曲记录功能
使用浏览器的持久储存 window.localStorage
来储存当前播放的歌曲,使得可以在页面重新载入后依然从该歌曲播放而不是重新从播放列表的第一首歌曲开始播放。
本例中使用 window.localStorage.setItem(key, value)
来将数据(键值对)写入浏览器的持久储存中;使用 window.loacalStorage.getItem(key)
来读取浏览器持久储存中对应的数据。
<script>
window.onload = function() {
let index = window.localStorage.getItem('musicId') ? window.localStorage.getItem('musicId') : 0;
let music = document.getElementById('music');
let controlOne = document.getElementById('controlOne');
let controlTwo = document.getElementById('controlTwo');
let controlThree = document.getElementById('controlThree');
let controlProgress = document.getElementById('controlProgress');
let playingProgress = document.getElementById('playingProgress');
let playingBar = document.getElementById('playingBar');
let nowTime = document.getElementById('nowTime');
let endTime = document.getElementById('endTime');
let musicList = document.getElementById('musicList');
let drag = 0;
let flag = 0;
nowTime.innerText = "00:00";
function getQueryString(str) {
let reg = new RegExp("(^|&)" + str + "=([^&]*)(&|$)");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
} else {
return null;
}
}
function getMin(min) {
let res = parseInt(min / 60);
if(res < 10) {
return '0' + res;
} else {
return res + '';
}
}
function getSec(min) {
let res = parseInt(min % 60);
if(res < 10) {
return '0' + res;
} else {
return res + '';
}
}
let timer = '';
let stop = '';
let dragTime = 0;
function musicPlay() {
music.play();
window.localStorage.setItem('musicId', music.getAttribute('data-index'));
timer = setInterval(() => {
let progressLen = music.currentTime / music.duration * controlProgress.clientWidth;
nowTime.innerText = getMin(music.currentTime) + ":" + getSec(music.currentTime);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
},1000);
}
function musicPause() {
music.pause();
clearInterval(timer);
}
class musicObj {
constructor(name, src, author, time) {
this.name = name;
this.src = src;
this.author = author;
this.time = time;
}
};
let musicNameList = ['MusicOne', 'MusicTwo', 'MusicThree'];
let musicSrcLsit = ['Demo0.mp3', 'Demo1.mp3', 'Demo2.mp3'];
let musicAuthorList = ['AuthorOne', 'AuthorTwo', 'AuthorThree'];
let musicTimeList = ['04:01', '02:00', '03:40'];
let musicListObj = new Array();
for(let i in musicNameList) {
musicListObj[i] = new musicObj(musicNameList[i], musicSrcLsit[i], musicAuthorList[i], musicTimeList[i]);
}
function playPrev() {
let dataIndex = parseInt(music.getAttribute('data-index'));
let prevIndex = (dataIndex - 1) < 0 ? musicListObj.length - 1 : (dataIndex - 1);
musicPause();
music.setAttribute('src', musicListObj[prevIndex].src);
music.setAttribute('data-index', prevIndex);
music.currentTime = 0;
nowTime.innerText = "00:00";
endTime.innerText = musicListObj[prevIndex].time;
controlTwo.className = "play-control-button pause";
playingProgress.style.width = 0 + 'px';
playingBar.style.marginLeft = 0 + 'px';
musicPlay();
}
function playNext() {
let dataIndex = parseInt(music.getAttribute('data-index'));
let nextIndex = (dataIndex + 1) > (musicListObj.length - 1) ? 0 : (dataIndex + 1)
musicPause();
music.setAttribute('src', musicListObj[nextIndex].src);
music.setAttribute('data-index', nextIndex);
music.currentTime = 0;
nowTime.innerText = "00:00";
endTime.innerText = musicListObj[nextIndex].time;
controlTwo.className = "play-control-button pause";
playingProgress.style.width = 0 + 'px';
playingBar.style.marginLeft = 0 + 'px';
musicPlay();
}
for(let i in musicListObj) {
let newNode = document.createElement('li');
newNode.setAttribute('data-src', musicListObj[i].src);
newNode.setAttribute('data-time', musicListObj[i].time);
newNode.setAttribute('data-index', i);
newNode.innerText = musicListObj[i].name + ' - ' + musicListObj[i].author;
musicList.appendChild(newNode);
}
controlTwo.addEventListener('click', () => {
console.log("Click");
if(controlTwo.className == "play-control-button play") {
controlTwo.className = "play-control-button pause";
musicPlay();
} else if (controlTwo.className == "play-control-button pause") {
controlTwo.className = "play-control-button play";
musicPause();
}
});
controlProgress.addEventListener('click', (e) => {
e = e || window.e;
let rate = ((e.clientX - controlProgress.getBoundingClientRect().left) / controlProgress.clientWidth);
let progressLen = e.clientX - controlProgress.getBoundingClientRect().left;
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
let theTime = parseInt(rate * (music.duration))
music.currentTime = theTime;
nowTime.innerText = getMin(theTime) + ":" + getSec(theTime);
console.log(rate);
});
playingBar.addEventListener('mousedown', () => {
console.log('mousedown');
drag = 1;
flag = 1;
clearInterval(timer);
});
document.addEventListener('mouseup', () => {
console.log('mouseup');
drag = 0;
if(flag == 1) {
music.currentTime = dragTime;
timer = setInterval(() => {
let progressLen = music.currentTime / music.duration * controlProgress.clientWidth;
nowTime.innerText = getMin(music.currentTime) + ":" + getSec(music.currentTime);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
},1000);
console.log('reStart');
}
flag = 0;
});
controlProgress.addEventListener('mousemove', (e) => {
e = e || window.e;
if(drag == 1) {
console.log('mousemove');
let progressLen = e.clientX - controlProgress.getBoundingClientRect().left;
let rate = (progressLen / controlProgress.clientWidth);
playingProgress.style.width = progressLen + 'px';
playingBar.style.marginLeft = progressLen - 4 + 'px';
let theTime = parseInt(rate * (music.duration));
nowTime.innerText = getMin(theTime) + ":" + getSec(theTime);
dragTime = theTime;
}
});
musicList.addEventListener('click', (e) => {
e = e || window.e;
let musicSrc = e.target.getAttribute('data-src');
let dataIndex = e.target.getAttribute('data-index');
musicPause();
music.setAttribute('src', musicSrc);
music.setAttribute('data-index', dataIndex);
music.currentTime = 0;
endTime.innerText = e.target.getAttribute('data-time');
musicPlay();
e.stopPropagation();
});
controlOne.addEventListener('click', () => {
playPrev();
});
controlThree.addEventListener('click', () => {
playNext();
});
music.addEventListener('ended', () => {
playNext();
});
music.src = musicListObj[index].src;
music.setAttribute('data-index', index);
endTime.innerText = musicListObj[index].time;
}
</script>
开始时对作为音乐顺序的 index
进行初始化(判断该页面是否第一次被载入);通过 index
来判断应该加载的歌曲。在音乐播放函数 musicPlay()
中写入目前正在播放的音乐在播放列表中的顺序(也可以在定时函数中将当前播放时间也写入,这样下一次可以从断点中继续播放)。