效果
原理
匹配歌曲时间和歌词对象数组,高亮,歌词被容器包裹
一个容器设置overflow:hidden;
包含ul
和歌词li
,计算ul transform:tranlateY()
,移动
方法
- 初始化
- 绑定事件
初始化
- 将获取到的数据,时间和歌词组合变成对象
// 1. 初始化
async function init() {
// 拿到歌词,生成li,放入到ul中
const lrc = await getLrc();
// 将lrc -> [ { time: 86.09, words: '这沙滚滚水皱皱笑着浪荡' } ....]
lrcData = lrc
.split('\n')
.filter((s) => s)
.map((s) => {
const parts = s.split(']');
const timeParts = parts[0].replace('[', '').split(':');
return {
time: +timeParts[0] * 60 + +timeParts[1],
words: parts[1],
};
});
// 生成li,加入到ul中
doms.ul.innerHTML = lrcData.map((lrc) => `<li>${lrc.words}</li>`).join('');
}
- 初始化常量,行高,容器高度
const doms = {
ul: document.querySelector('.lrc'),
audio: document.querySelector('audio'),
};
const size = {
liHeight: 30,
containerHeight: 420,
};
- 当前歌曲时间匹配对象数组(数组查找第一个数据大于当前事件-1),查找并高亮
歌词高亮 歌词滚动
/**
* 根据播放时间,设置好歌词的状态
* @param {*} time
*/
function setStatus(time) {
// 微调
time += 0.5;
// 根据时间找到对应的li,高亮
// 消除之前的active
const activeLi = document.querySelector('.active');
activeLi && activeLi.classList.remove('active');
const index = lrcData.findIndex((lrc) => lrc.time > time) - 1;
if (index < 0) {
return;
}
doms.ul.children[index].classList.add('active');
//2. 设置ul的滚动位置
let top =size.liHeight * index + size.liHeight / 2 - size.containerHeight / 2;
top = -top;
if (top > 0) {
top = 0;
}
doms.ul.style.transform = `translateY(${top}px)`;
}