写一个音乐播放器2--歌词高亮滚动
按照惯例,先上效果图:
实现
书接上回,实现了进度条写一个音乐播放器1--歌曲播放进度条,现在来实现歌词布局与歌词随歌曲播放高亮滚动功能。
html部分
采用无序列表ul
加v-for
实现歌词布局,一行一句歌词,默认中间行为当前播放歌词,高亮显示它。
<audio ref="player" autoplay ></audio>
<div class="detail">
<div class="song-title">
<p ref="song">歌名</p>
<p ref="singer">歌手</p>
</div>
<div class="wrapper">
<ul ref="ul" class="content">
<li v-for="(item,index) of ms" :key=item.index>{{item.c}}</li>
</ul>
</div>
</div>
scss样式部分
这里高亮当前播放歌词,采用动态样式绑定,lineHigh类为高亮样式。
.detail {
position: absolute;
top: 1rem;
bottom: 2.6rem;
left: 0;
right: 0;
text-align: center;
color: #26a2ff;
.song-title {
width: 100%;
height: 2rem;
p {
width: 100%;
line-height: .8rem;
font-size: 18px;
color: #FFD700;
margin-top: .1rem;
text-align: center;
}
}
.wrapper {
overflow: hidden;
position: absolute;
top: 2rem;
right: 0;
left: 0;
height: 545px;
ul {
line-height: 32px;
width: 100%;
padding-bottom: 1rem;
li {
font-size: 16px;
transition-duration: 1200ms;
}
.lineHigh {
color: #FFD700;
}
}
}
}
JS部分
布局完成,现在来实现给当前播放歌词绑定高亮lineHigh和随着歌曲播放向上滚动歌词。
高亮歌词
ms
是按每行歌词存储改行歌词与改行歌词开始播放时间的数组;
lineNo
为当前播放歌曲词行数,初始值为0
;
遍历歌词数组,判断歌词滚动时间是否等于当前歌词开始播放时间,
若是则lineNo+1,开始播放第一句,标记当前正在播放歌词;
给lineNo改行歌词加上lineHigh高亮样式。
data () {
return {
lineNo: 0,
Cpos: 7,
offset: -32,
ms: [],
}
},
mounted () {
const music = this.$refs.player // 音频所在对象
const ulist = this.$refs.ul
const curTime = music.currentTime; // 歌词滚动时间
music.addEventListener('timeupdate', () => {
if(this.lineNo==this.ms.length) return;
const curTime = music.currentTime; //播放器时间
if(parseFloat(this.ms[this.lineNo].t) <= curTime){
this.lineHigh();//高亮当前行
this.lineNo++;
}
})
music.addEventListener('ended', () => {
this.goback(); //回滚歌词
music.play()
})
}
滚动歌词
Cpos
为高亮屏幕中的第几行歌词,
Cpos
这里设置为7
,意在将高亮歌词置于屏幕中间位置;
offset
为每行歌词高度,这里是每个li的高度为32px
;
当前歌词还没到第7行时,高亮改该行不用滚动歌词;
当歌词到达第7行之后,需向上滚动歌词,滚动距离为当前播放的歌词行数(lineNo-Cpos) * offset
,
即为在播放第八行时,需要向上滚动一行,采用translateY
实现向上滚动。
并且注意给歌词父盒子wrapper要设置属性overflow: hidden;
隐藏歌词超出部分。
注意
:向上滚动一行高亮当前行时需移出上一行的高亮样式。
methods: {
// 高亮歌词滚动事件
lineHigh() {
const ulist = this.$refs.ul
const list = ulist.getElementsByTagName("li");
if(this.lineNo>0){
list[this.lineNo-1].removeAttribute("class");//去掉上一行的高亮样式
}
list[this.lineNo].className = "lineHigh";//高亮显示当前行
//文字滚动
if(this.lineNo > this.Cpos){
ulist.style.transform = "translateY("+(this.lineNo-this.Cpos)*this.offset+"px)";
//整体向上滚动一行高度
}
},
// 重新播放是歌词重置事件
goback() {
const ulist = this.$refs.ul
document.querySelector(".lineHigh").removeAttribute("class");
ulist.style.transform = "translateY(0)";
this.lineNo = 0; //lineNo清零,重新播放
},
}
然后是播放结束,重新开始播放,重新开始播放调用audio的API play
即可重新开始播放,重新回滚至歌词第一行,将lineNo重置为0
。
最后
至此,歌词随歌曲播放滚动高亮已完成,接下来就是将歌词滚动与进度条进度同步,敬请期待下一篇吧。

转载自:https://juejin.cn/post/7131708339905363981