基本布局
<div class="musicBox">
<ul id="showLyric">
</ul>
<p class="musicFoot">
<audio src="music/于此与彼.mp3" controls="controls" autoplay="autoplay"></audio>
<br/>
</p>
</div>
样式
* {
padding: 0;
margin: 0;
}
html,body,div,p,ul {
margin: 0;
padding: 0;
}
html,body {
background-color: rgba(110, 170, 150, 0.4);
height: 100%;
width: 100%;
}
.musicBox {
height: 100%;
}
ul,li {
list-style: none;
}
ul{
height:80%;
background-color: aqua;
overflow-y: hidden;
}
li {
text-align: center;
font-size: 13px;
height: 20px;
line-height: 20px;
}
audio{
height: 30px;
width: 115%;
margin-left: -5%;
margin-top: 12%;
}
.musicFoot {
position: fixed;
bottom: 0;
height: 20%;
width: 100%;
background-color: mediumpurple;
}
button{
height: 30px;
width: 25%;
margin-left: 20px;
}
.lineheight{
color: brown;
font-size: 15px;
background-color: antiquewhite;
}
歌词
[ti:]
[ar:]
[al:]
[by:]
[offset:0]
[00:02.01]与彼于此 - 庞琪祥
[00:04.03]词:张鑫
[00:06.05]曲:张鑫
[00:08.06]编曲:杨朝焰/黄汇雯
[00:10.08]制作人:杨朝焰
[00:13.00]和声:Isabell潘沁珈
[00:15.01]吉他:王保为
[00:17.03]录音:王一名
[00:19.05]混音:王楷尧
[00:21.07]母带:王楷尧
[00:23.08]监制:赵晨
[00:26.00]商务统筹:丁聪
[00:28.02]制作统筹:陈嘉琪
[00:30.03]Op:万有YIN力
[00:32.05]发行公司:万有YIN力
[00:34.07]游来游去忽远忽近
[00:37.07]予取予求半信半疑
[00:40.04]莫名不安和恐惧
[00:46.00]绘声绘色毕恭毕敬
[00:48.07]百依百顺不离不弃
[00:51.04]尝试用面具肯定
[00:57.07]眺望你眼中迷离的风景
[01:03.01]蓝色里透着淡定
[01:08.05]嘴里的愿意 还有都可以
[01:13.01]如此随心所欲游刃有余
[01:21.02]我们还该不该相信彼此
[01:26.09]保留最后一份
[01:29.06]当初最真挚的样子
[01:34.06]初遇时的相似
[01:38.00]如今是分道扬镳的关键词
[01:43.02]我们还要不要拥抱彼此
[01:48.09]用曾经最熟悉的
[01:52.03]而现在不愿的方式
[01:57.01]努力放逐灵魂
[02:01.00]任回忆放肆
[02:05.04]让抚平了的心跳
[02:09.06]再循环一次
[02:29.03]眺望你眼中迷离的风景
[02:34.08]蓝色里透着淡定
[02:37.02]嘴里的愿意 还有都可以
[02:44.07]如此随心所欲游刃有余
[02:49.04]我们还该不该相信彼此
[02:54.09]保留最后一份
[02:57.06]当初最真挚的样子
[03:02.08]初遇时的相似
[03:06.02]如今是分道扬镳的关键词
[03:11.03]我们还要不要拥抱彼此
[03:16.07]用曾经最熟悉的
[03:20.04]而现在不愿的方式
[03:24.06]努力放逐灵魂 任回忆放肆
[03:32.09]让抚平了的心跳 再循环一次
[03:49.03]我们还该不该相信彼此
[03:54.07]保留最后一份
[03:57.04]当初最真挚的样子
[04:02.03]初遇时的相似
[04:05.08]如今是分道扬镳的关键词
[04:10.07]我们还要不要拥抱彼此
[04:16.00]用曾经最熟悉的
[04:19.04]而现在不愿的方式
[04:23.07]努力放逐灵魂 任回忆放肆
[04:31.07]让抚平了的心跳 再循环一次
处理歌词,得到每行歌词以及相应时间
/* 步骤1:
显示歌词在歌词容器中
*/
// 处理歌词:将字符串转化为数组
let part=lyric.split('\n')
// console.log(part)
for(let index=0;index<part.length;index++){
// 将数组内的 值处理成:时间+歌词
part[index]=getObj(part[index])
}
console.log(part)
// 处理每行歌词
function getObj(partContent){
// 将每行切分成:时间+歌词
let twoParts=partContent.split(']')
// 获取时间
let time=twoParts[0].substr(1)
// 将时间切分成:分+秒
let timeParts=time.split(':')
// console.log(timeParts)
let timeSeconds=timeParts[1]
let second=Number(timeSeconds)
let timeMinutes=timeParts[0]
let minutes=Number(timeMinutes)
// 保留两位小数
let seconds=(minutes * 60 +second).toFixed(2)
let words=twoParts[1]
return{
seconds,
words
}
}
将歌词显示在页面上
let part=lyric.split('\n')
// console.log(part)
let liStr=''
for(let index=0;index<part.length;index++){
// 将数组内的 值处理成:时间+歌词
part[index]=getObj(part[index])
liStr+='<li>'+part[index]['words']+'</li>'
}
oul.innerHTML=liStr
歌词高亮以及滚动
查看歌词容器相关属性值
console.log('歌词容器的可视高度:'+oul.clientHeight)
console.log('歌词容器的实际高度:'+oul.scrollHeight)
console.log('歌词距离容器顶部的偏移:'+lis[12].offsetTop)
console.log('歌词滚出可视区域的距离:'+oul.scrollTop)
// 歌词滚动效果
function heightLyric(linenum){
// 1、歌词高亮
// linenum:歌词行号
let ul=document.getElementById('showLyric')
if(linenum>0){
// 当前播放的前一行取消高亮显示,移除相关类
lis[linenum-1].removeAttribute("class")
}
// 歌词当前播放行
let nowline=lis[linenum]
nowline.setAttribute("class","lineheight")
// 2、歌词滚动
let _scrollTop=0;//歌词滚动出去的距离
ul.scrollTop=0//初始,歌词滚出容器的距离为0
let coefficient=0.5
// 当歌词位于可视区域上面,则不滚动
//歌词可视区域高度的一半>当前歌词距离容器顶部偏移
if(ul.clientHeight*coefficient>nowline.offsetTop){
_scrollTop=0
//当前行距离顶部频移 >(歌词容器实际距离-可视容器距离的一半
}else if(nowline.offsetTop>(ul.scrollHeight-ul.clientHeight*(1-coefficient))){
// 当最后一行歌词出现在可视区域,则不再向上滚动
_scrollTop=ul.scrollHeight-ul.clientHeight
}else{
// 否则,滚动
_scrollTop=nowline.offsetTop-ul.clientHeight*coefficient
}
/* 当前行距离顶部的偏移-滚动的距离>歌词可视区的一半
说明:当前行在可视区域一半的位置以下,需要向上滚动 */
if((nowline.offsetTop-ul.scrollTop)>ul.clientHeight*coefficient){
ul.scrollTop+=Math.ceil(nowline.offsetTop-ul.scrollTop-ul.clientHeight*coefficient)
}else if((nowline.offsetTop-ul.scrollTop)<ul.clientHeight*coefficient && _scrollTop!=0){
//当前歌词在可视区域一半以上
ul.scrollTop -=Math.ceil(ul.clientHeight*coefficient-(nowline.offsetTop-ul.scrollTop))
}else if(_scrollTop==0){
ul.scrollTop=0
}else{
ul.scrollTop+=lis[linenum].clientHeight
}
}
获取歌词中存在歌词的首行的索引
let i=0
let linenum=0
do{
i++
}while(lis[i].innerHTML =='undefined'|| lis[i].innerHTML==''){
linenum=i
}
// console.log('linenum'+linenum)
音频监听,歌词滚动
音频监听事件
audio.addEventListener('timeupdate',lyricScroll)
audio.addEventListener('timeupdate',function lyricScroll(){
if(linenum==part.length-1 && audio.currentTime.toFixed(2) >= parseFloat(part[linenum]['seconds'])){
heightLyric(lineno)
}
if(audio.currentTime.toFixed(2) >= parseFloat(part[linenum]['seconds']) && audio.currentTime.toFixed(2)<=parseFloat(part[linenum+1]['seconds'])){
heightLyric(linenum)
linenum++
}
})