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.解析歌词 拿到时间和歌词
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.总结
自己慢慢摸索做出来的,感觉还是不错!
更多推荐
所有评论(0)