Vue实现歌词解析+滚动效果

1.获取歌词(字符串格式)

调用接口,从后台拿到歌词数据,默认是字符串格式 像这样

 let lyric = "
 [by:小懒猫stad]
 [00:02.689]我多想回到那个夏天
 [00:05.939]蝉鸣在田边吹过眼睫
 [00:09.948]贪恋夏夜星空你侧脸
 [00:13.197]犹记得清风撩拨心弦
 [00:17.162]初夏的味道是你微笑
 [00:20.343]我捧着月亮别来无恙
 "

2.解析歌词 拿到时间和歌词存放在对象数组里

2.1 拿到每一行歌词

我们可以用正则匹配换行字符对字符串进行分割

const regNewLine = /\n/
const lineArr = lyric.split(regNewLine) // 每行歌词的数组

这样就拿到了每一行歌词的数组

2.2 分隔时间和歌词

这里用正则来匹配中括号里面的时间

const regTime = /\[\d{2}:\d{2}.\d{2,3}\]/

对lineArr数组进行遍历分隔

lineArr.forEach(item => {
     
 if (item === '') return
  const obj = {
     }
  const time = item.match(regTime)

  obj.lyric = item.split(']')[1].trim() === '' ? '' : item.split(']')[1].trim()
  obj.time = time ? this.formatLyricTime(time[0].slice(1, time[0].length - 1)) : 0
  obj.uid = Math.random().toString().slice(-6)
  if (obj.lyric === '') {
     
    console.log('这一行没有歌词')
  } else {
     
    lyricsObjArr.push(obj)
  }
})

这里需要注意的是 ①时间获取出来是包含中括号的,要用slice截取一下,并且要转成(秒.毫秒 88.9)格式 这样才方便与audio的currentTime进行对比 ②有些时间后面没有歌词,所以我们要把这一行给去掉 所有就有代码下面的if判断

这里有一个转换时间的函数 formatLyricTime 代码如下 比较粗糙

formatLyricTime (time) {
      // 格式化歌词的时间 转换成 sss:ms
     const regMin = /.*:/
     const regSec = /:.*\./
     const regMs = /\./

     const min = parseInt(time.match(regMin)[0].slice(0, 2))
     let sec = parseInt(time.match(regSec)[0].slice(1, 3))
     const ms = time.slice(time.match(regMs).index + 1, time.match(regMs).index + 3)
     if (min !== 0) {
     
       sec += min * 60
     }
     return Number(sec + '.' + ms)
   }

lyricsObjArr这就是最终生成的数组了格式是这样的:

lyricsObjArr : [
	{
     
		time: 34.5,
		lyric: '爱上你是我情非得已',
		uid: '234432'
	},
	{
     
		time: 64.5,
		lyric: 'WDNMD非得已',
		uid: '233332'
	}
]

3.循环数据 渲染dom

html结构

<ul ref="lyricUL">
   <li v-for="(item, i) in lyricsObjArr" :style="{
        color: lyricIndex === i ? 'skyblue' : '#ded9d9'}" :key="item.uid" :data-index='i' ref="lyric">{
    {item.lyric}}li>
 ul>

4.歌词滚动

在audio的timeupdate事件是进行监听 具体思路是:
循环 lyricsObjArr 数组 拿到时间并与 currentTime 进行对比 如果 currentTime 大于歌词时间 拿到当前 li 标签 data-index 的值 和循环的 i 进行对比 如果相同就更新data里面的 lyricIndex 值 用它来绑定颜色,同时控制外层 ul 标签的滚动 改变他的 transfrom:translateY() 的值。 具体代码如下

// 匹配歌词
for (let i = 0; i < this.lyricsObjArr.length; i++) {
     
    if (this.currentTime > (parseInt(this.lyricsObjArr[i].time))) {
     
      const index = this.$refs.lyric[i].dataset.index
      if (i === parseInt(index)) {
     
        this.lyricIndex = i
        this.$refs.lyricUL.style.transform = `translateY(${
       170 - (30 * (i + 1))}px)`
      }
    }
  }

5.总结

自己慢慢摸索做出来的,感觉还是不错!

你可能感兴趣的:(vue,js,es6,ios,audio,queue,services,file)