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

[项目]实现歌词滚动

作者: 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