编写一个属于自己的音乐播放器-歌词滚动功能

508 阅读1分钟

闲来无事,研究了音乐播放器的歌词滚动功能

首先,要找到你想编写的某一首歌的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文件,来编写对于歌词的一些格式化以及生成内容。
  1. 将歌词格式化为{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
}
  1. 将时间进行格式化(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…)]