美文网首页
歌曲播放页面的实现

歌曲播放页面的实现

作者: sweetBoy_9126 | 来源:发表于2019-01-10 22:37 被阅读4次
    1.点击首页的列表跳转到对应歌曲

    实现方法:通过点击的时候把对应的id传入作为查询参数,跳转的时候去新的页面使用window.location.search读取查询参数里的id

    • page-1-1.js
    <a class="playButton" href="./song.html?id=${song.id}">
         <svg class="icon icon-play">
             <use xlink:href="#icon-play"></use>
         </svg>
    </a>
    
    • app.js
    let view = {
      el: '#app',
      init(){
         this.$el = $(this.el)
      }
    }
    let model = {
            data: {
                id: '',
                name: '',
                singer: '',
                url: ''
            },
            getSong(id){
                var song = new AV.Query('Song')
                return song.get(id).then(data=>{
                    Object.assign(this.data,data.attributes)
                    return this.data
                })
            }
        }
        let controller = {
            init(view, model){
                this.view = view
                this.model = model
                this.view.init()
                this.getId()
                this.model.getSong(this.model.data.id)
                    .then(()=>{
                        this.view.render(this.model.data)
                    })
                this.bindEvent()    
            },
            getId(){
                //这里拿到的是带问好的查询参数如:?id=454444
                let search = window.location.search
                let id = ''
                if(search){
                    var idOne = search.substring(1).split('&')
                    idOne.map(list=>{
                        var keyValue = list.split('=')
                        var idKey = keyValue[0]
                        id = keyValue[1]
                    })
                }
                this.model.data.id = id
            },
        }
    
    2.实现歌曲的播放暂停

    实现方法:通过拿到的id对应的歌曲信息,将当前的audio里的url占位符替换,然后通过给按钮添加play方法来播放,pause方法来暂停

    • app.js
    let view = {
      template: `
                <audio src="__url__"></audio>
                <div>
                    <button class="play">播放</button>
                    <button class="pause">暂停</button>
                </div>
            `,
            init(){
                this.$el = $(this.el)
            },
            render(data){
                let audio =this.template.replace('__url__',data.url)
                this.$el.html(audio)
            },
            play(){
                this.$el.find('audio')[0].play()
            },
            pause(){
                this.$el.find('audio')[0].pause()
            }
    }
    let controller = {
      bindEvent(){
                this.view.$el.on('click','.play',()=>{
                    console.log(1)
                    this.view.play()
                })
                this.view.$el.on('click','.pause',()=>{
                    this.view.pause()
                })
            }
    }
    

    使用ended监听歌曲结束,然后调用暂停事件

    3.歌词的获取和位置滚动

    实现方法:拿到一个原始的带时间轴的歌词,先通过\n(换行)来将歌词拆分成数组,然后用map遍历,拿到每一行的时间轴和歌词,比如:'[00:00:00]薛之谦:天份',然后通过正则将左右拆开分别拿到左边的时间轴和右侧的文字,之后在当前map先创建p标签,每个p的文字内容就是上面拿到的右侧的文字,然后将左侧的时间轴变成秒的形式,加到p的自定义属性中,最后通过一个timeupdate事件拿到audio.currentTime,然后遍历你当前的p元素,将当前播放时间currentTime于上一句歌词和下一句歌词比较,如果它小于等于上一句歌词(i)的时间并且小于下一句(i+1)的歌词时间,那么就获取这个p距顶部的距离和拿到这个p,找到了就break退出循环,如果i等于allP.length-1也就是最后一句的话,就直接显示最后一句然后break,然后就可以拿到每一秒对应的p的高度,之后就给它的父集一个translatY(对应的高度)即可

    <div class="song-description">
      <h1></h1>
      <div class="lyric">
        <div class="lines">
                        
        </div>
      </div>
    </div>
    let view = {
      render(data){
        let {song,status} = data
        this.audioListener(song)
        let {lyric} = song
        lyric.split('\n').map(string=>{
            let textTimer = string.match(/\[[\d:.]+\]/)
            let time = textTimer[0].match(/[\d:.]+/)[0]
            let text = string.replace(`[${time}]`,'')
            let $p = $('<p></p>').text(text)
            this.$el.find('.lines').append($p)
            let minuterSecond = time.split(':')
            let [minuter,second] = minuterSecond
            second = parseFloat(minuter) * 60 + parseFloat(second)
            $p.attr('data-time',second)
        })  
    },
    getCurrentTime(time){
        let allP = this.$el.find('.lines > p')
        for(let i = 0;i<allP.length;i++){
            if(i===allP.length-1){
                var p = allP[i]
                break
            }else {
                var prevtime = allP[i].getAttribute('data-time')
                var nexttime = allP[i+1].getAttribute('data-time')
                if(prevtime <= time && time < nexttime){
                    p = allP[i]
                    break
                }
            }   
        }
        let originalHeight = $(p)[0].getBoundingClientRect().top
        $(p).addClass('active').siblings().removeClass('active')
        let parentHeight = this.$el.find('.lyric> .lines')[0].getBoundingClientRect().top
        let height = parentHeight - originalHeight + 20
        this.lyricMove(height)
    },
    audioListener(song){
        //重新渲染的时候如果audio里的src是#就让它等于当前的song.url否则,就不去重新渲染
        if(this.$el.find('audio').attr('src') !== song.url){
            let audio = this.$el.find('audio').attr('src',song.url)
            audio.on('timeupdate',()=>{
                this.getCurrentTime(audio[0].currentTime)
            })
        }
    },
    lyricMove(height){
        this.$el.find('.lines').css('transform',`translateY(${height}px)`)
    }
    }
    

    相关文章

      网友评论

          本文标题:歌曲播放页面的实现

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