音乐播放页歌词与声音对应展示

347 阅读2分钟

需求:分割后台传递过来的歌词用来做播放音乐实时显示当前歌词

传递过来的格式: [00:22.50]你一直在身边\n[00:25.92]如果世界太危险\n...

      data: {
            // 歌词信息
            lyric: []
      },
//建议把下面的方法放到utils文件夹封装使用
//创建时间匹配正则
const timeReg = /\[(\d{2}):(\d{2}).(\d{2,3})]/
//传入请求过来的所有歌词
function parseLyric(lyric) {
    const lyricRes = []
    //把歌词按照\n进行分割
    const lyricInfo = lyric.split('\n')
    //分割出来的歌词循环
    for (const lyricString of lyricInfo) {
    //正则匹配歌词
        const res = timeReg.exec(lyricString)
        //一整句都不匹配的退出循环
        if (!res) continue
        //分转为ms
        const m = Number(res[1] * 60 * 1000)
        //秒转为ms
        const s = Number(res[2] * 1000)
        //两位数的ms后面需要+加个0
        const ms = Number(res[3].length == 2 ? res[3] * 10 : res[3])
        //合并所有ms
        const lyricTime = m + s + ms
        //把前面的时间替换为空,留下文本
        const lyricText = lyricString.replace(res[0], '')
        //向数组里传入对象{时间,文本}
        lyricRes.push({ time: lyricTime, text: lyricText })
    }
    return lyricRes
}
//接收返回数组
const lyric = parseLyric(res.lrc.lyric)
this.setData({ lyric })

需求:播放音乐实时显示当前歌词

       data: {
            // 当前歌词
            currentLyrics: '',
            // 当前歌词index
            currentLyricsIndex: -1
       },
    
    //监听音频播放进度更新
    innerAudioContext.onTimeUpdate(() => {
        // 如果data中没有获取到歌词信息,退出
        if (!this.data.lyric.length) return
        //默认显示第一句歌词
        let index = 0
        //for循环歌词长度
        for (let i = 0; i < this.data.lyric.length; i++) {
        //每循环一次拿出当前这句歌词
            const lyric = this.data.lyric[i]
            //如果这句歌词需要显示的时间大于当前播放时间并且index>0,否则会报错
            if (lyric.time > innerAudioContext.currentTime * 1000 && i > 0) {
            //就让index-1,否则会显示下一句歌词
                index = i - 1
                //找到后退出循环
                break
            }
        }
        //如果当前这句歌词的index已经记录过了,退出,否则会多次重复记录影响性能
        if (this.data.currentLyricsIndex == index) return
        //找出最后一句歌词的显示时间
        const totalTime = this.data.lyric[this.data.lyric.length-1].time
        //如果当前播放时间大于最后一句歌词的显示时间
        if(innerAudioContext.currentTime * 1000>totalTime){
        //就让index保持在最后(一直显示最后一句歌词)
            index = this.data.lyric.length-1
        }
        //如果没有记录,就记录当前这句歌词的index
        const currentLyricsIndex = index
        this.setData({ currentLyrics: this.data.lyric[index].text, currentLyricsIndex })
    })