美文网首页
[项目]实现歌词滚动

[项目]实现歌词滚动

作者: Camilia_yang | 来源:发表于2019-07-22 18:02 被阅读0次

需求:当音乐播放到某一句时,出现对应的歌词。
【静态】render歌词
1.拿到LRC歌词(字符串)后string.split('\n')。每一行生成一个p标签。
2.用正则解析每一行成两部分(时间和歌词)。歌词部分作为p标签的文本,时间部分作为每个p标签data-time属性的值。
3.因为LRC歌词给的时间是形如[01:02.00]的,所以要先解析成和currentTime一样的格式(62.00)

let string = song.lyrics
string.split('\n').map((string)=>{
    let p = document.createElement('p')
    let regex = /\[([\d:.]+)\](.+)/
    let matches =string.match(regex)
    if(matches){
        p.textContent = matches[2]
        let array=matches[1].split(':')
        let mins=array[0]
        let seconds=array[1]
        let newTime=parseInt(mins)*60+parseFloat(seconds)
        $(p).attr('data-time', newTime)
     }else{
        p.textContent = string
     }
     $('.lines').append(p)
})  

【动态】滚动歌词
【Controller】
查看文档,发现audio元素的timeupdate事件可以监听audio元素currentTime(返回以秒为单位的当前媒体元素的播放时间)的每一次改变(MDN解释:The time indicated by the element's currentTime attribute has changed)
所以,我们监听timeupdate事件,在currentTime每一次改变时,去调用 view的showLyric()方法,同时将currentTime传给View。

$(this.view.el).find('audio').get(0).ontimeupdate=()=>{
  let audio=$(this.view.el).find('audio').get(0)
  this.view.showLyric(audio.currentTime,this.model.data.currentP)
}

【View】

showLyric(time,lastP){
      //找到对应p标签
            let $allP=this.$el.find('.lines>p')
            let currentP
            //当i=$allP.length-1时,$allP.eq(i+1)不存在,会报错,所以要判断一下。
            for(i=0;i<$allP.length;i++){
                if(i===$allP.length-1){
                    currentP=$allP[i]
                    break
                }else{
                    let prevTime=$allP.eq(i).attr('data-time')
                    let nextTime=$allP.eq(i+1).attr('data-time')
                    if(prevTime<=time&&time<=nextTime){
                        currentP=$allP[i]
                        break
                    }   
                }
            }
      // 高亮p标签
         $(currentP).addClass('active').siblings('.active').removeClass('active')

      //核心代码:
      //如果找到的p标签和上一个一样,说明不需要进行歌词滚动
      //如果不一样,则说明需要滚动一行
         if(currentP!==lastP){
                window.eventHub.emit('selectP',currentP)
                this.$el.find('.lines').css('transform',`translateY(${-(24*i-24)}px)`)
            }
        }             

1.遍历p标签,找到当前播放的歌词p标签,currentP。
2.在model的data里添加一个变量currentP,当找到跟currentTime匹配的p标签时,则触发自定义的‘selectP’事件,将该p标签传出去,在controller的里监听‘selectP’事件,将接收到的p标签写到model的data.currentP上。
在调用view.showLyric()时,将model.data.currentP作为第二个参数传过去,和新找到的p标签对比,如果一样,则不滚动歌词,如果不一样,则滚动一行(p标签的line-height)

相关文章

网友评论

      本文标题:[项目]实现歌词滚动

      本文链接:https://www.haomeiwen.com/subject/lxswlctx.html