闲来无事,研究了音乐播放器的歌词滚动功能
首先,要找到你想编写的某一首歌的lrc歌词,我这里以 "将故事写成我们"为例 lrc歌词格式为[00.00.00]xxxxx
新建一个.js文件 将lrc歌词放入该js文件中(以下的lrc歌词只是其中的一部分,想要看全部可以去我的git上查看[(github.com/cy9886/lyri…])
let lrc = `
[00:00.00]
[00:00.57]林俊杰 - 将故事写成我们
[00:01.44]作词:方文山
[00:01.64]作曲:林俊杰
[00:33.39]这最美的秘密
[00:36.97]是我们都在制造巧遇
[00:40.49]谁说幸福 只是一种
[00:44.16]远方的消息
[00:47.30]思念持续着浓郁
[00:51.23]梦甘甜下去
[00:53.86]誓言继续
...`
紧接着,再创建一个.js文件,来编写对于歌词的一些格式化以及生成内容。
- 将歌词格式化为{time:'xxx',name:'xxx'}的格式
function parseLrc () {
let arr = [] // 歌词数组
let lines = lrc.split('\n') // 当前歌词
let line; // 每一行的歌词
for (let i = 1; i < lines.length; i++) {
line = lines[i]
let parts = line.split(']')
let timeStr = parts[0].substring(1) // 这里利用toString()的方法是因为需要从'['之后截取到末尾
let obj = { // 这里是拼接成一个新对象
time: time2number(timeStr),
name: parts[1]
}
arr.push(obj)
}
return arr
}
- 将时间进行格式化(mm:ss)
function time2number (str) {
let parts = str.split(':')
let minutes = parts[0] * 60
let seconds = parts[1]
return minutes + +seconds
}
现在格式化的一些操作完成了,该去对歌词进行一些计算了
1.要获取一些相关的dom元素
let doms = {
audio: document.querySelector('audio'),
ul: document.querySelector('ul'),
container: document.querySelector('.container')
}
2.要计算在格式化之后的数据中,应该高亮的歌词下标,就需要知道当前的播放器播放到了第几秒钟(audio中自带apicurrentTime可查看当前歌词播放到了某时刻)
function findIndex () {
let currentTime = doms.audio.currentTime // 当前播放时间
for (let i = 0; i < lrcData.length; i++) {
if (currentTime < lrcData[i].time) { // 如果当前播放器时间小于歌词的时间 证明现在应该高亮歌词下标的上一句
return i - 1
}
}
return lrcData.length - 1 //这里是考虑到开头和结尾,不能计算有负数,所以给一个边界值
}
3.创建歌词列表元素
function createList () {
for (let i = 0; i < lrcData.length; i++) {
let li = document.createElement('li')
li.textContent = lrcData[i].name
doms.ul.appendChild(li)
}
}
最后,设置ul的相关偏移量即可
let containerHeight = doms.container.clientHeight // 容器高度
let liHeight = doms.ul.children[0].clientHeight // li高度
let maxHeight = doms.ul.clientHeight - containerHeight // 最大高度
function setOffset () {
let index = findIndex()
let offset = liHeight * index + liHeight / 2 - containerHeight / 2
if (offset < 0) { //如果当前还没有开始播放
offset = 0
}
if (offset > maxHeight) { // 当前歌词位置在最后一句
offset = maxHeight
}
doms.ul.style.transform = `translateY(-${offset}px)`
// doms.ul.children[index].classList = 'active'
// 去掉之前的active
let active = doms.ul.querySelector('.active')
if (active) {
active.classList.remove('active')
}
let li = doms.ul.children[index]
if (li) {
li.classList.add('active')
}
}
doms.audio.addEventListener('timeupdate',setOffset)
相关的样式文件以及html文件,可在[git中获取(github.com/cy9886/lyri…)]