使用HTML+CSS+JS做一个音乐播放器
2021-03-01 20:25
YPE html>
标签:charset 自动 防止 pre substr 结果 设置 bottom ogre
一、观前说明:
1.本人为新手,很多地方可能写得不好,欢迎指正。
2.本人仍在学习CSS中,在本篇中若有写得不好的地方,欢迎指正。
3.本人尚未系统性的学习过JS(还没学到),在这里用到的JS全是靠以前学其他语言积累下的基础,因此在很多地方也会写得不够好,欢迎指正。
4.因HTML部分和CSS部分较为简单,本篇文章会更注重于讲JS部分,其中一些说明我会写在代码里面,我认为这比我写在外面更好理解。
5.我是将整个播放器写完了才写的这篇文章,所以你们在看代码的时候,会看到一些提前写了的代码,比如播放暂停还没讲到修改时间间距,但在代码处已经有了。
二、最终效果
2.1、包含功能
1.播放暂停
2.歌词动画,显示当前歌词
3.拖拽歌词,调整歌词进度
4.进度条调整歌词进度
5.音量控制
2.2、图片展示
三、现在开始
1.搭建基础框架
框架图:
按照框架图,搭建框架:
其中歌词是后面由JS创建的,因此只需要有一个div包住就行
音乐播放器
专辑:
歌手:
00:00
00:00/00:00
100
2.CSS美化
2.1清除所有边距已经禁止选择
* {
margin: 0;
padding: 0;
user-select: none;
}
h1 {
font-weight: 500;
}
a {
color: #000;
text-decoration: none;
}
2.2设置背景样式(大盒子)
/* 背景样式,相当于body */
.background {
width: 100vw;
height: 100vh;
background-color: #fff;
}
/* 上半部分样式,即包含封面以及歌词的盒子 */
.music-background {
width: 1000px;
height: calc(100vh - 200px);
margin: 0 auto;
overflow: hidden;
}
/* 图片盒子 */
.img-back {
width: 300px;
padding: 0 50px;
margin-top: 150px;
margin-right: 50px;
overflow: hidden;
float: left;
}
/* 歌词盒子 */
.lyrics-back {
width: 550px;
height: 100%;
overflow: hidden;
float: left;
}
/* 歌曲信息盒子 */
.div-title {
width: 100%;
height: 100px;
margin-top: 150px;
}
/* 控制区域盒子 */
.control-back {
width: 100vw;
height: 80px;
bottom: 0;
position: absolute;
background-color: rgba(255, 255, 255, 0.8);
}
2.3设置图片、字体样式
只是简简单单的调整大小边距等,甚至在歌曲信息中的文字段落标签我都没有设置字体大小,事实上这并不是一种好的习惯
.img-back img {
width: 300px;
height: 300px;
border-radius: 20px;
}
.div-title h1 {
width: 100%;
height: 50px;
}
.div-title p {
height: 50px;
display: inline-block;
color: rgba(0, 0, 0, 0.5);
}
.div-title span {
color: #000;
}
.div-lyrics p {
font-size: 15px;
line-height: 34px;
}
2.4设置控制按钮、进度条、音量控制样式
这里我的控制按钮用的都是a标签,因此需要将a标签修改为行内块标签inline-block
其中".lyrics-time"是拖拽歌词时显示的调整进度的按钮,因此在默认状态下需要隐藏
.lyrics-time a {
display: inline-block;
position: absolute;
display: none;
}
.goto {
width: 20px;
height: 20px;
margin: 7px 15px;
background: url(../img/play.png) no-repeat;
background-position: 50% 50%;
background-size: 20px;
}
.goto-time {
width: 50px;
height: 34px;
margin-left: 550px;
font-size: 13px;
line-height: 34px;
text-align: center;
position: absolute;
color: #5192fe;
}
/* 进度条 */
.progress-bar {
width: calc(100vw - 100px);
margin: 5px 0;
padding: 5px 0;
cursor: pointer;
float: left;
}
/* 当前播放进度 */
.progress-now {
width: 0;
height: 1px;
margin-top: -1px;
background-color: #5192fe;
}
/* 总播放进度 */
.progress-all {
width: 100%;
height: 1px;
background-color: #dee2e6;
}
/* 播放进度 文本 */
.time {
display: inline-block;
width: 90px;
height: 21px;
margin-left: 5px;
text-align: center;
color: rgba(128, 130, 133, 0.8);
cursor: default;
overflow: hidden;
}
/* 控制按钮 */
.control {
width: 100%;
height: 30px;
margin-top: 19px;
}
.control a {
margin: 0 5px;
display: inline-block;
}
.control a:hover {
opacity: 50%;
}
.control-btn {
width: 130px;
height: 30px;
margin: 0 auto;
}
/* 上一首 */
.up {
width: 30px;
height: 30px;
background: url(../img/up.png) no-repeat;
background-size: 20px;
background-position: 50% 50%;
}
/* 暂停播放 */
.play-pause {
width: 30px;
height: 30px;
background: url(../img/play.png) no-repeat;
background-size: 30px;
background-position: 50% 50%;
}
/* 下一首 */
.down {
width: 30px;
height: 30px;
background: url(../img/down.png) no-repeat;
background-size: 20px;
background-position: 50% 50%;
}
/* 右侧控制按钮 */
.control-right {
/* width: 180px; */
height: 30px;
margin-left: calc(50vw + 150px);
margin-top: -30px;
display: flex;
align-items: center;
}
/* 播放模式 */
.mode {
width: 30px;
height: 30px;
background: url(../img/sequence.png) no-repeat;
background-size: 20px;
background-position: left 50%;
cursor: pointer;
}
/* 声音控制 */
.volume {
width: 30px;
height: 30px;
background: url(../img/volume.png) no-repeat;
background-size: 20px;
background-position: left 50%;
cursor: pointer;
}
.volume-back {
padding: 5px 0;
cursor: pointer;
}
.volume-all {
width: 100px;
height: 2px;
background-color: #e5e5e5;
}
.volume-now {
width: 100px;
height: 2px;
margin-top: -2px;
max-width: 100px;
background-color: #5192fe;
}
.volume-text {
margin-left: 10px;
font-size: 14px;
}
3.JS部分
3.1首先是声明一些变量、数组等,因为这一部分是要多处使用的,因此在最开头就声明了
var myAduio = document.getElementsByTagName(‘audio‘)[0];
var divLyrics = document.getElementsByClassName(‘div-lyrics‘)[0];
var divTitle = document.getElementsByClassName(‘div-title‘)[0];
var lyricsTime = document.getElementsByClassName(‘lyrics-time‘)[0];
var lyricsTime_a = lyricsTime.getElementsByTagName(‘a‘);
var progressTime = document.getElementsByClassName(‘time‘)[0];
var nowLine = 0;
var lyricsMove = false;
var playState = false;
var lyrics, lyricsStyle, lyricsFirst, rollT;
var timeArray1 = new Array();
var timeArray2 = new Array();
var timeInterval = new Array();
这里面分别是
audio控件,播放音乐用的;
歌词div,到时候要在这里面创建歌词
歌曲信息div,也是在这里面修改歌曲信息的内容
拖拽歌词调整进度的div "lyricsTime"以及里面的按钮 "lyricsTime_a"
进度条右侧的时间"progressTime"
当前播放行"nowLine"
拖拽状态"lyricsMove"
播放状态"playState"
所有歌词的p标签"lyrics",第一行歌词的样式"lyricsStyle",第一行歌词的p标签"lyricsFirst",歌词滚动的计时器"rollT"
以秒数记录每一行歌词所在时间的数组"timeArray1"以及以分钟:秒数的星石记录每一行歌词所在时间的数组"timeArray2",用两种方式记录时间的原因是后面需要以这两种形式交叉使用,也可以只记录一种,在使用到另一种的时候将其算出来,但我感觉直接记录两种会更方便
记录每一行歌词时间间距的数组"timeInterval"
3.2页面加载完毕后就需要执行的方法
window.onload = function () {
initialLyrics();
lyricsStyle = getComputedStyle(lyricsFirst, null);
setLyrics(0);
setMouseEvent();
setTimeText();
};
3.3初始化歌词(创建歌词并存储一些信息)
sp、ar、ti分别为专辑、艺术家、歌名
function initialLyrics() {
let sp = divTitle.getElementsByTagName(‘span‘)[0];
let ar = divTitle.getElementsByTagName(‘span‘)[1];
let ti = divTitle.getElementsByTagName(‘h1‘)[0];
let lyricsData, timeString;
let lyricsArray = new Array();
// 清除数组,先清除数组可以保证每一次存储的信息无误
timeArray1.splice(0, timeArray1.length);
timeArray2.splice(0, timeArray2.length);
lyricsArray.splice(0, lyricsArray.length);
// 按相同格式放入歌词更换歌曲即可达到相同效果
lyricsData =
‘[ar]韩安旭\n[ti]不在\n[sp]不在\n[00:00.74]韩安旭 - 不在\n[00:01.76]词:尤雅琪\n[00:02.76]曲:胜屿\n[00:15.62]我累了就紧紧锁住情绪\n[00:18.11]不再放任它堆积\n[00:22.14]我痛了就静静屏住呼吸\n[00:26.02]不给想念留余地\n[00:28.88]只是下雨时会委屈\n[00:32.80]只是想起你会哭泣\n[00:36.77]没关系 真没关系\n[00:44.28]我终于学会一个人弹琴\n[00:47.12]只是弹琴没有你\n[00:49.29]我终于学会一个人做梦\n[00:54.85]只是做梦没有你\n[00:57.73]我依旧像从前粗心\n[01:01.09]时常会忘记星期几\n[01:05.00]却始终忘不掉你看我的眼睛\n[01:11.71]穿过了熙攘的人海\n[01:15.11]想找谁能把你取代\n[01:19.62]复制你曾给过我的\n[01:21.44]那种宠爱\n[01:26.32]掏空了回忆的脑海\n[01:30.75]寂寞却狠狠扑过来\n[01:33.69]措手不及 无法躲开\n[01:41.52]我承认是我太依赖\n[01:44.92]像个不懂事的小孩\n[01:48.35]挥霍掉我们的未来\n[01:51.22]才醒过来\n[01:55.15]我承认后悔了伤害\n[01:59.06]抛开你的好我的坏\n[02:02.14]直到如今学会忍耐 你不在\n[02:26.95]我终于学会一个人弹琴\n[02:29.33]只是弹琴没有你\n[02:33.26]我终于学会一个人做梦\n[02:36.64]只是做梦没有你\n[02:39.53]我依旧像从前粗心\n[02:42.90]时常会忘记星期几\n[02:46.82]却始终忘不掉你看我的眼睛\n[02:53.62]穿过了熙攘的人海\n[02:57.09]想找谁能把你取代\n[03:00.98]复制你曾给过我的\n[03:05.43]那种宠爱\n[03:08.25]掏空了回忆的脑海\n[03:11.67]寂寞却狠狠扑过来\n[03:15.56]措手不及 无法躲开\n[03:22.49]我承认是我太依赖\n[03:26.37]像个不懂事的小孩\n[03:30.38]挥霍掉我们的未来\n[03:33.80]才醒过来\n[03:37.81]我承认后悔了伤害\n[03:41.29]抛开你的好我的坏\n[03:44.73]直到如今学会忍耐 你不在‘;
// 文本.split(‘分隔符‘),用于分割文本
lyricsArray = lyricsData.split(‘\n‘);
// 添加歌曲信息
ar.innerText = lyricsArray[0].split(‘]‘)[1];
ti.innerText = lyricsArray[1].split(‘]‘)[1];
sp.innerText = lyricsArray[2].split(‘]‘)[1];
// 添加歌词
for (var i = 3; i ‘ +
lyricsArray[i].split(‘]‘)[1] +
‘‘;
} else {
divLyrics.innerHTML +=
‘‘ + lyricsArray[i].split(‘]‘)[1] + ‘
‘;
}
}
// 获取后续需要使用的变量
lyricsFirst = divLyrics.getElementsByTagName(‘p‘)[0];
lyrics = divLyrics.getElementsByTagName(‘p‘);
// 计算每局歌词所在的秒数
timeArray1.push(0);
for (var i = 0; i
歌词初始化完后,整个页面就可以正常显示了,接下来先写控制播放暂停的功能
3.3播放暂停
// 设置播放状态
function setPlay(state) {
var play_pause = document.getElementsByClassName(‘play-pause‘)[0];
if (state == null) {
// 如果歌曲为暂停状态,那么获取到的state则为true,将state设置为true我们就播放
state = myAduio.paused;
}
// 清除计时器,不然会出现多个计时器同时进行
clearTimeout(rollT);
if (state == true) {
myAduio.play();
play_pause.style.backgroundImage = ‘url(../img/pause.png)‘;
playState = true;
// 开始播放的同时,同时开始设置时间进度文本,歌词滚动以及进度条位置
setTimeText();
lyricsRoll();
setProgress();
} else {
myAduio.pause();
play_pause.style.backgroundImage = ‘url(../img/play.png)‘;
playState = false;
// 暂停后重新修改计时器时间,这里后面会详细讲
timeInterval[nowLine] = timeArray1[nowLine + 1] - myAduio.currentTime;
}
}
3.4设置时间进度文本
// 设置进度文本
function setTimeText() {
var nowTime = myAduio.currentTime;
var allTime = myAduio.duration;
// 计算时间,若为个位数,补0
if (Math.floor(nowTime % 60)
3.5设置进度条位置
// 设置进度条进度
function setProgress() {
let progress_now = document.getElementsByClassName(‘progress-now‘)[0];
let progress_bar = document.getElementsByClassName(‘progress-bar‘)[0];
let progress = Math.floor(
(myAduio.currentTime / myAduio.duration) * progress_bar.clientWidth
);
progress_now.style.width = progress + ‘px‘;
if (myAduio.paused == false) {
setTimeout(setProgress, 100);
}
}
到这里,除了歌词滚动、调整进度等,一个最简单的音乐播放器就已经完成了
3.6设置歌词位置
// 设置歌词位置
function setLyrics(line) {
// 将当前歌词高亮,其余歌词都改为黑色
for (let i = 0; i
设置歌词写好了,我们现在就需要考虑如何让歌词滚动起来,即让歌词自动到达当前行的位置
我想到的方法有两种
第一种方法是根据每句歌词之间的时间间隔,每过一个间隔,就触发一次方法,我这里用的就是这种方法;
第二种方法是每过很短的一段时间,就触发一次方法,就跟进度条类似;
我观察过酷狗以及QQ音乐,其中酷狗用的应该就是第一种方法,是过一个间隔触发一次的,而QQ音乐则是用的第二种方法。
我个人认为第二种方法写起来更简单,但是需要的性能更高,但是进度条、以及时间进度文本是必须使用第二种方法的(至少我想不到其他的),那么如果将进度条、时间进度文本、歌词滚动这三个方法放在一个计时器中调用,而不是像我这样分开三个计时器,哪一种是更优的方法就不得而知了,欢迎各位大佬给出自己的看法。
那么我们这里用第一种方法,首先我们先分析一下需要记录的内容(其实前面已经记录了,只是在这里才说)
第一个是要记录歌词,这个不需要多的解释,显示用的
第二个需要记录时间间隔,这个是用来设置计时器的
第三个需要记录每一行歌词所在的时间,分两个记录,一个按秒数记录,用来拖拽歌词时调整进度;另一个按分:秒记录,用于拖拽歌词时显示时间;两个数组可只记录一个,用到另一个的时候算出来就好,我为了方便就记录了两个
前面三个都是要用数组记录,第四个则是非数组,用于记录当前歌词到了哪一行,在歌词滚动中,歌词回弹等地方都会用到。
需要记录的东西我们分析完了,那么接下来在画一个逻辑图来分析计时器要如何设置,即歌词滚动要如何实现
分析完毕,那么继续
3.7歌词滚动
// 歌词滚动
// 歌词滚动的方法只需要按照时间间隔设置计时器即可
function lyricsRoll() {
rollT = setTimeout(function () {
if (nowLine
到这里,播放器的歌词滚动部分已经写好了,但现在的播放器只能播放暂停,看到歌词在哪,不能调整进度等,接下来我们就来解决这个问题
3.8歌词拖拽、音量控制、调整进度
function setMouseEvent() {
// 歌词拖拽
let lyrics_Y, line;
// 此处是调整歌词位置,以及计算用户将歌词拖拽到了哪一行
divLyrics.onmousedown = function (e) {
if (lyricsMove == false) {
lyricsTime_a[0].style.display = lyricsTime_a[1].style.display = lyricsTime.style.display =
‘block‘;
lyricsMove = true;
}
lyrics_Y = parseInt(lyricsStyle.marginTop);
document.onmousemove = function (event) {
lyricsFirst.style.marginTop =
event.clientY - (e.clientY - lyrics_Y) + ‘px‘;
line = Math.floor(-(parseInt(lyricsStyle.marginTop) - 170) / 34);
if (line lyrics.length - 1) {
line = lyrics.length - 1;
}
lyricsTime_a[1].innerText = timeArray2[line];
};
document.onmouseup = function () {
// Y1的作用是判断用户是否仍处于拖拽状态,若一秒后歌词位置仍等于Y1,则判断为非拖拽状态,但这样写有一个bug就是如果只是按住鼠标不进行拖拽,则也会判断为非拖拽状态,暂时想不到解决方法
var lyrics_Y1 = parseInt(lyricsStyle.marginTop);
setTimeout(function () {
if (parseInt(lyricsStyle.marginTop) == lyrics_Y1) {
lyricsMove = false;
setLyrics(nowLine);
lyricsTime_a[0].style.display = lyricsTime_a[1].style.display = lyricsTime.style.display =
‘none‘;
}
}, 1000);
// 清除鼠标移动方法的同时也一定要清除鼠标弹起方法,不然每次点击页面都会调用这个方法
document.onmousemove = null;
document.onmouseup = null;
};
// 防止选中文字
return false;
};
// 音量控制
// 音量控制没什么好说的,需要注意的是volume的音量是从0-1,所以在设置音量时要将其除以100
let volume_now = document.getElementsByClassName(‘volume-now‘)[0];
let volume_back = document.getElementsByClassName(‘volume-back‘)[0];
let volume_text = document.getElementsByClassName(‘volume-text‘)[0];
let volume_a = document.getElementsByClassName(‘volume‘)[0];
volume_back.onmousedown = function (e) {
volume_now.style.width = e.offsetX + ‘px‘;
myAduio.volume = e.offsetX / 100;
volume_text.innerText = volume_now.clientWidth;
volume_back.onmousemove = function (ev) {
let volume = ev.offsetX;
if (volume > 100) {
volume = 100;
}
volume_now.style.width = volume + ‘px‘;
myAduio.volume = volume / 100;
volume_text.innerText = volume_now.clientWidth;
};
document.onmouseup = function () {
// 如果音量为0,更换静音图片,否则更换非静音图片
if (myAduio.volume == 0) {
volume_a.style.backgroundImage = ‘url(../img/mute.png)‘;
} else {
volume_a.style.backgroundImage = ‘url(../img/volume.png)‘;
}
volume_back.onmousemove = null;
document.onmouseup = null;
};
return false;
};
// 进度控制
// 进度控制跟音量控制一样,只需要注意算法就好
// 从之前的设置进度条进度我们可用知道,进度条的宽度=当前播放进度/歌曲总时长*进度条总长
// 所以 当前播放进度=进度条宽度/进度条总长*歌曲总时长
let progress_now = document.getElementsByClassName(‘progress-now‘)[0];
let progress_bar = document.getElementsByClassName(‘progress-bar‘)[0];
progress_bar.onmousedown = function (e) {
progress_now.style.width = e.offsetX + ‘px‘;
myAduio.pause();
myAduio.currentTime =
(e.offsetX * myAduio.duration) / progress_bar.clientWidth;
setTimeText();
progress_bar.onmousemove = function (ev) {
let progress = ev.offsetX;
if (progress > progress_bar.clientWidth) {
progress = progress_bar.clientWidth;
}
progress_now.style.width = progress + ‘px‘;
myAduio.currentTime =
(progress * myAduio.duration) / progress_bar.clientWidth;
setTimeText();
};
document.onmouseup = function () {
myAduio.play();
for (var i = 0; i
3.9设置静音
这个比较简单,就不说了
// 设置静音
function setMuted() {
let volume_now = document.getElementsByClassName(‘volume-now‘)[0];
let volume_text = document.getElementsByClassName(‘volume-text‘)[0];
let volume_a = document.getElementsByClassName(‘volume‘)[0];
if (myAduio.muted == true) {
myAduio.muted = false;
volume_a.style.backgroundImage = ‘url(../img/volume.png)‘;
volume_now.style.width = myAduio.volume * 100 + ‘px‘;
volume_text.innerText = myAduio.volume * 100;
} else {
myAduio.muted = true;
volume_a.style.backgroundImage = ‘url(../img/mute.png)‘;
volume_now.style.width = ‘0‘;
volume_text.innerText = ‘0‘;
}
}
到这里,我们的整个播放器就已经全部完成了
以下是完整代码
HTML
音乐播放器
专辑:
歌手:
00:00
00:00/00:00
100
CSS
* {
margin: 0;
padding: 0;
user-select: none;
}
h1 {
font-weight: 500;
}
a {
color: #000;
text-decoration: none;
}
/* 背景板 */
.background {
width: 100vw;
height: 100vh;
background-color: #fff;
}
/* 歌词封面背景 */
.music-background {
width: 1000px;
height: calc(100vh - 200px);
margin: 0 auto;
overflow: hidden;
}
/* 封面背景 */
.img-back {
width: 300px;
padding: 0 50px;
margin-top: 150px;
margin-right: 50px;
overflow: hidden;
float: left;
}
.img-back img {
width: 300px;
height: 300px;
border-radius: 20px;
}
/* 歌词背景 */
.lyrics-back {
width: 550px;
height: 100%;
overflow: hidden;
float: left;
}
/* 歌曲信息 */
.div-title {
width: 100%;
height: 100px;
margin-top: 150px;
}
.div-title h1 {
width: 100%;
height: 50px;
}
.div-title p {
height: 50px;
display: inline-block;
color: rgba(0, 0, 0, 0.5);
}
.div-title span {
color: #000;
}
.div-lyrics {
height: calc(100vh - 450px);
overflow: hidden;
position: relative;
}
.div-lyrics p {
font-size: 15px;
line-height: 34px;
}
/* 歌词进度 */
.lyrics-time {
width: 650px;
height: 34px;
margin-top: 136px;
margin-left: -50px;
position: absolute;
display: none;
}
.lyrics-time a {
display: inline-block;
position: absolute;
display: none;
}
.goto {
width: 20px;
height: 20px;
margin: 7px 15px;
background: url(../img/play.png) no-repeat;
background-position: 50% 50%;
background-size: 20px;
}
.goto-time {
width: 50px;
height: 34px;
margin-left: 550px;
font-size: 13px;
line-height: 34px;
text-align: center;
position: absolute;
color: #5192fe;
}
/* 控制背景 */
.control-back {
width: 100vw;
height: 80px;
bottom: 0;
position: absolute;
background-color: rgba(255, 255, 255, 0.8);
}
/* 进度条 */
.progress-bar {
width: calc(100vw - 100px);
margin: 5px 0;
padding: 5px 0;
cursor: pointer;
float: left;
}
/* 当前播放进度 */
.progress-now {
width: 0;
height: 1px;
margin-top: -1px;
background-color: #5192fe;
}
/* 总播放进度 */
.progress-all {
width: 100%;
height: 1px;
background-color: #dee2e6;
}
/* 播放进度 文本 */
.time {
display: inline-block;
width: 90px;
height: 21px;
margin-left: 5px;
text-align: center;
color: rgba(128, 130, 133, 0.8);
cursor: default;
overflow: hidden;
}
/* 控制按钮 */
.control {
width: 100%;
height: 30px;
margin-top: 19px;
}
.control a {
margin: 0 5px;
display: inline-block;
}
.control a:hover {
opacity: 50%;
}
.control-btn {
width: 130px;
height: 30px;
margin: 0 auto;
}
/* 上一首 */
.up {
width: 30px;
height: 30px;
background: url(../img/up.png) no-repeat;
background-size: 20px;
background-position: 50% 50%;
}
/* 暂停播放 */
.play-pause {
width: 30px;
height: 30px;
background: url(../img/play.png) no-repeat;
background-size: 30px;
background-position: 50% 50%;
}
/* 下一首 */
.down {
width: 30px;
height: 30px;
background: url(../img/down.png) no-repeat;
background-size: 20px;
background-position: 50% 50%;
}
/* 右侧控制按钮 */
.control-right {
/* width: 180px; */
height: 30px;
margin-left: calc(50vw + 150px);
margin-top: -30px;
display: flex;
align-items: center;
}
/* 播放模式 */
.mode {
width: 30px;
height: 30px;
background: url(../img/sequence.png) no-repeat;
background-size: 20px;
background-position: left 50%;
cursor: pointer;
}
/* 声音控制 */
.volume {
width: 30px;
height: 30px;
background: url(../img/volume.png) no-repeat;
background-size: 20px;
background-position: left 50%;
cursor: pointer;
}
.volume-back {
padding: 5px 0;
cursor: pointer;
}
.volume-all {
width: 100px;
height: 2px;
background-color: #e5e5e5;
}
.volume-now {
width: 100px;
height: 2px;
margin-top: -2px;
max-width: 100px;
background-color: #5192fe;
}
.volume-text {
margin-left: 10px;
font-size: 14px;
}
JS
var myAduio = document.getElementsByTagName(‘audio‘)[0];
var divLyrics = document.getElementsByClassName(‘div-lyrics‘)[0];
var divTitle = document.getElementsByClassName(‘div-title‘)[0];
var lyricsTime = document.getElementsByClassName(‘lyrics-time‘)[0];
var lyricsTime_a = lyricsTime.getElementsByTagName(‘a‘);
var progressTime = document.getElementsByClassName(‘time‘)[0];
var nowLine = 0;
var lyricsMove = false;
var playState = false;
var lyrics, lyricsStyle, lyricsFirst, rollT;
var timeArray1 = new Array();
var timeArray2 = new Array();
var timeInterval = new Array();
window.onload = function () {
initialLyrics();
lyricsStyle = getComputedStyle(lyricsFirst, null);
setLyrics(0);
setMouseEvent();
setTimeText();
};
// 设置事件
function setMouseEvent() {
// 歌词拖拽
let lyrics_Y, line;
divLyrics.onmousedown = function (e) {
if (lyricsMove == false) {
lyricsTime_a[0].style.display = lyricsTime_a[1].style.display = lyricsTime.style.display =
‘block‘;
lyricsMove = true;
}
lyrics_Y = parseInt(lyricsStyle.marginTop);
document.onmousemove = function (event) {
lyricsFirst.style.marginTop =
event.clientY - (e.clientY - lyrics_Y) + ‘px‘;
line = Math.floor(-(parseInt(lyricsStyle.marginTop) - 170) / 34);
if (line lyrics.length - 1) {
line = lyrics.length - 1;
}
lyricsTime_a[1].innerText = timeArray2[line];
};
document.onmouseup = function () {
var lyrics_Y1 = parseInt(lyricsStyle.marginTop);
setTimeout(function () {
if (parseInt(lyricsStyle.marginTop) == lyrics_Y1) {
lyricsMove = false;
setLyrics(nowLine);
lyricsTime_a[0].style.display = lyricsTime_a[1].style.display = lyricsTime.style.display =
‘none‘;
}
}, 1000);
document.onmousemove = null;
document.onmouseup = null;
};
// 防止选中文字
return false;
};
// 音量控制
let volume_now = document.getElementsByClassName(‘volume-now‘)[0];
let volume_back = document.getElementsByClassName(‘volume-back‘)[0];
let volume_text = document.getElementsByClassName(‘volume-text‘)[0];
let volume_a = document.getElementsByClassName(‘volume‘)[0];
volume_back.onmousedown = function (e) {
volume_now.style.width = e.offsetX + ‘px‘;
myAduio.volume = e.offsetX / 100;
volume_text.innerText = volume_now.clientWidth;
volume_back.onmousemove = function (ev) {
let volume = ev.offsetX;
if (volume > 100) {
volume = 100;
}
volume_now.style.width = volume + ‘px‘;
myAduio.volume = volume / 100;
volume_text.innerText = volume_now.clientWidth;
};
document.onmouseup = function () {
if (myAduio.volume == 0) {
volume_a.style.backgroundImage = ‘url(../img/mute.png)‘;
} else {
volume_a.style.backgroundImage = ‘url(../img/volume.png)‘;
}
volume_back.onmousemove = null;
document.onmouseup = null;
};
return false;
};
// 进度控制
let progress_now = document.getElementsByClassName(‘progress-now‘)[0];
let progress_bar = document.getElementsByClassName(‘progress-bar‘)[0];
progress_bar.onmousedown = function (e) {
progress_now.style.width = e.offsetX + ‘px‘;
myAduio.pause();
myAduio.currentTime =
(e.offsetX * myAduio.duration) / progress_bar.clientWidth;
setTimeText();
progress_bar.onmousemove = function (ev) {
let progress = ev.offsetX;
if (progress > progress_bar.clientWidth) {
progress = progress_bar.clientWidth;
}
progress_now.style.width = progress + ‘px‘;
myAduio.currentTime =
(progress * myAduio.duration) / progress_bar.clientWidth;
setTimeText();
};
document.onmouseup = function () {
myAduio.play();
for (var i = 0; i ‘ +
lyricsArray[i].split(‘]‘)[1] +
‘‘;
} else {
divLyrics.innerHTML +=
‘‘ + lyricsArray[i].split(‘]‘)[1] + ‘
‘;
}
}
// 获取后续需要使用的变量
lyricsFirst = divLyrics.getElementsByTagName(‘p‘)[0];
lyrics = divLyrics.getElementsByTagName(‘p‘);
// 计算每局歌词所在的秒数
timeArray1.push(0);
for (var i = 0; i
其中JS中,获取页面属性跟歌词回弹是没有用到的,获取页面属性我写是&am