Vue网易音乐歌词处理滚动高亮 您所在的位置:网站首页 vue页面自动滚动 Vue网易音乐歌词处理滚动高亮

Vue网易音乐歌词处理滚动高亮

2023-04-04 22:53| 来源: 网络整理| 查看: 265

Vue网易音乐歌词处理滚动高亮

对于网易歌词数据我们要先几个步骤处理歌词,并解析拿到我们所需要的数据,因为播放器是全局的,数据就存放再vuex里,拿取数据也方便,其中要对vuex要用一定的了解,vuex中的数据,方法都是通过映射拿到

Gitee项目地址

效果图,部分功能还未完善

QQ截图20230330145033.png

歌词处理

获取歌词

处理歌词,拿到想要的数据

渲染

(1)调用网易的歌词api用axios获取数据,因为歌词获取异步,我就把调用写在了vuex中,后续调用更方便,实现复用性

调用formatLyr方法,参数是获取的歌词并把方法返回解析后的歌词存储到state中,下方的数据处理借鉴于黑马程序员

actions:{ async songlyric (context) { //lyricAPI 是封装的axios const { data: res } = await lyricAPI({ id: context.state.playList[context.state.playListIndex].id }) context.commit('updatelyric', await this.dispatch('formatLyr', res.lrc.lyric)) } } 复制代码

(2)定义方法处理歌词 ,处理歌曲时间

actions:{ formatLyr (context, lyricStr) { // 可以看network观察歌词数据是一个大字符串, 进行拆分. const reg = /\[.+?\]/g // const timeArr = lyricStr.match(reg) // 匹配所有[]字符串以及里面的一切内容, 返回数组 // console.log(timeArr) // ["[00:00.000]", "[00:01.000]", ......] const contentArr = lyricStr.split(/\[.+?\]/).slice(1) // 按照[]拆分歌词字符串, 返回一个数组(下标为0位置元素不要,后面的留下所以截取) // console.log(contentArr) const lyricObj = {} // 保存歌词的对象, key是秒, value是显示的歌词 const songSet = [] timeArr.forEach((item, index) => { // 拆分[00:00.000]这个格式字符串, 把分钟数字取出, 转换成秒 const ms = item.split(':')[0].split('')[2] * 60 // 拆分[00:00.000]这个格式字符串, 把十位的秒拿出来, 如果是0, 去拿下一位数字, 否则直接用2位的值 const ss = item.split(':')[1].split('.')[0].split('')[0] === '0' ? item.split(':')[1].split('.')[0].split('')[1] : item.split(':')[1].split('.')[0] // 秒数作为key, 对应歌词作为value lyricObj[ms + Number(ss)] = [contentArr[index], ms + Number(ss)] songSet.push(ms + Number(ss)) // lyricObj[item] = ms + Number(ss) // lyricObj.push({ms + Number(ss)}) }) // 返回得到的歌词对象(可以打印看看 context.commit('updateCurLyric', lyricObj[0][0]) context.commit('updateSongTime', songSet) return lyricObj }, // 格式化播放时长 歌曲时间处理,获取的时间是毫秒 formatDt (context, time) { const dt = time / 1000 let m = parseInt(dt / 60) let s = parseInt(dt % 60) m = m >= 10 ? m : (m = '0' + m) s = s >= 10 ? s : (s = '0' + s) context.commit('updateSongFore', m + ':' + s) } } 复制代码

(3)下面是在定义在state的变量

lyric: {}, // 歌词枚举对象(需要在js拿到歌词写代码处理后, 按照格式保存到这个对象) curLyric: '', // 当前显示哪句歌词 lastLy: '', // 记录当前播放歌词 currenTime: '', // 当前播放时间 songTime: '', // 歌曲歌词对应时间 songFore: '' // 歌曲时长 复制代码

(4)定义在mutations中的方法改变state

mutations:{ updatelyric (state, val) { state.lyric = val }, updateCurLyric (state, val) { state.curLyric = val }, updateLastLy (state, val) { state.lastLy = val }, updateCurrenTime (state, val) { state.currenTime = val }, updateSongTime (state, val) { state.songTime = val }, updateSongFore (state, val) { state.songFore = val } } 复制代码

数据拿到后可以打印看看解析后的歌词,是以对象存储,key就是每句歌词对应的时间,后面高亮更加方便查询

歌词.png

渲染歌词

:class="{ acter: (currenTime >= item[1]) }" 给已播放的歌词添加样式,当前播放时间大于或等于这句歌词的时间

:style="{ 'font-size': (currenTime >= item[1] && currenTime < songTime[(Number((Object.keys(lyric)).indexOf(i))) + 1]) || curLyric[1] === item[1] ? '.5rem' : '' }" 这是当前正在播放的歌词添加字体变大样式 因为拿到的歌词有些时间对应的歌词为空,所以还要添加判断

{{ item[0] }} 复制代码 获取当前播放时间

给audio定义一个ref,拿到当前时间并返回vuex 监听了音频播放器的timeupdate事件,以获取当前播放时间。然后,它使用当前时间作为索引来获取对应的歌词。如果当前时间对应的歌词不为空,它会将其更新为当前歌词。如果当前时间对应的歌词为空,它会将上一个非空歌词更新为当前歌词。这样,就可以实现在播放过程中实时切换歌词的效果

showLyric () { let curTime // 监听播放audio进度, 切换歌词显示 this.$refs.audio.addEventListener('timeupdate', () => { // 进度 curTime = Math.floor(this.$refs.audio.currentTime) this.updateCurrenTime(curTime) // 避免空白出现 // console.log(this.lyric[curTime]) if (typeof this.lyric[curTime] !== 'undefined' && this.lyric[curTime][0] !== String('\n')) { this.updateCurLyric(this.lyric[curTime]) this.updateLastLy(this.curLyric) } else { this.updateCurLyric(this.lastLy) } }) }, 复制代码

现在完成大概就是这样,页面布局看个人

1.png

歌词随页面随时间滚动

因为技术有限我的方法是改变父元素的scrollTOP,原则上vue是避免操作DOM的,有人的方法是设置TOP,但是设置了TOP后,就不能自己滚动页面了

歌词随时间滚动,首先就要监听我们拿到的当前播放时间,在watch中监听

因为curLyric中存储的是当前播放的歌词还有当前时间,判断当前时间于当前歌词时间,因为有些歌曲的时间有重复,所以我们先对songTime去重,再用foeEach循环判断,这里用some应该还要好点,看个人选择。(-200 + index * 40)其中-200是刚好到屏幕中间的位置,这个因人而异不重要,index当前判断为true的下标,相当于前面已经播放了多句歌词,再*每句歌词的高度,我高度给的是四十

watch: { currenTime () { // 先去重 [...new Set(this.songTime)].forEach((element, index) => { if (element === this.curLyric[1]) { document.querySelector('.songLyric').scrollTop = -200 + index * 40 } }) //下面item是当前播放的时间转换成 00:00格式 let m = parseInt(this.currenTime / 60) let s = parseInt(this.currenTime % 60) m = m >= 10 ? m : (m = '0' + m) s = s >= 10 ? s : (s = '0' + s) this.item = m + ':' + s //判断是否播放完,然后执行下一首方法 if (this.item === this.$store.state.songFore) { this.nextSong() } } }, 复制代码 歌曲详情页功能基本已经实现,第一次写这个,技术有限,还请见谅,有兴趣可以去顶部看看源码


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有